@tencent-connect/openclaw-qqbot 1.6.5-alpha.3 → 1.6.5-alpha.5
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 +1 -1
- package/README.zh.md +1 -1
- package/package.json +6 -2
- package/scripts/upgrade-via-npm.sh +179 -189
- package/scripts/upgrade-via-alt-pkg.sh +0 -307
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
**Connect your AI assistant to QQ — private chat, group chat, and rich media, all in one plugin.**
|
|
12
12
|
|
|
13
|
-
### 🚀 Current Version: `v1.6.
|
|
13
|
+
### 🚀 Current Version: `v1.6.5`
|
|
14
14
|
|
|
15
15
|
[](./LICENSE)
|
|
16
16
|
[](https://bot.q.qq.com/wiki/)
|
package/README.zh.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
**让你的 AI 助手接入 QQ — 私聊、群聊、富媒体,一个插件全搞定。**
|
|
11
11
|
|
|
12
|
-
### 🚀 当前版本: `v1.6.
|
|
12
|
+
### 🚀 当前版本: `v1.6.5`
|
|
13
13
|
|
|
14
14
|
[](./LICENSE)
|
|
15
15
|
[](https://bot.q.qq.com/wiki/)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tencent-connect/openclaw-qqbot",
|
|
3
|
-
"version": "1.6.5-alpha.
|
|
3
|
+
"version": "1.6.5-alpha.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -22,7 +22,11 @@
|
|
|
22
22
|
"id": "openclaw-qqbot",
|
|
23
23
|
"extensions": [
|
|
24
24
|
"./dist/index.js"
|
|
25
|
-
]
|
|
25
|
+
],
|
|
26
|
+
"channel": {
|
|
27
|
+
"id": "qqbot",
|
|
28
|
+
"label": "QQ Bot"
|
|
29
|
+
}
|
|
26
30
|
},
|
|
27
31
|
"scripts": {
|
|
28
32
|
"build": "tsc || true",
|
|
@@ -1,22 +1,27 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
2
|
|
|
3
|
-
# qqbot 通过
|
|
3
|
+
# qqbot 通过 openclaw 原生插件指令升级
|
|
4
4
|
#
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
5
|
+
# 使用 openclaw plugins install/update 原生命令进行安装和升级,
|
|
6
|
+
# 保留 appid/secret 配置写入、热更新 (--no-restart)、结构化输出等功能。
|
|
7
|
+
#
|
|
8
|
+
# 升级策略:
|
|
9
|
+
# 1. 已安装(plugins.installs 有记录)→ openclaw plugins update
|
|
10
|
+
# 2. 未安装 / update 失败 → 删除旧目录 + openclaw plugins install
|
|
8
11
|
#
|
|
9
12
|
# 用法:
|
|
10
13
|
# upgrade-via-npm.sh # 升级到 latest(默认)
|
|
11
14
|
# upgrade-via-npm.sh --version <version> # 升级到指定版本
|
|
12
15
|
# upgrade-via-npm.sh --self-version # 升级到当前仓库 package.json 版本
|
|
13
16
|
# upgrade-via-npm.sh --appid <appid> --secret <secret> # 首次安装时配置 appid/secret
|
|
14
|
-
# upgrade-via-npm.sh --no-restart
|
|
17
|
+
# upgrade-via-npm.sh --no-restart # 只做文件替换,不重启 gateway(供热更指令使用)
|
|
15
18
|
|
|
16
19
|
set -eo pipefail
|
|
17
20
|
|
|
18
21
|
PKG_NAME="@tencent-connect/openclaw-qqbot"
|
|
22
|
+
PLUGIN_ID="openclaw-qqbot"
|
|
19
23
|
INSTALL_SRC=""
|
|
24
|
+
TARGET_VERSION=""
|
|
20
25
|
APPID=""
|
|
21
26
|
SECRET=""
|
|
22
27
|
NO_RESTART=false
|
|
@@ -56,16 +61,19 @@ while [[ $# -gt 0 ]]; do
|
|
|
56
61
|
case "$1" in
|
|
57
62
|
--tag)
|
|
58
63
|
[ -z "$2" ] && echo "❌ --tag 需要参数" && exit 1
|
|
64
|
+
TARGET_VERSION="$2"
|
|
59
65
|
INSTALL_SRC="${PKG_NAME}@$2"
|
|
60
66
|
shift 2
|
|
61
67
|
;;
|
|
62
68
|
--version)
|
|
63
69
|
[ -z "$2" ] && echo "❌ --version 需要参数" && exit 1
|
|
70
|
+
TARGET_VERSION="$2"
|
|
64
71
|
INSTALL_SRC="${PKG_NAME}@$2"
|
|
65
72
|
shift 2
|
|
66
73
|
;;
|
|
67
74
|
--self-version)
|
|
68
75
|
[ -z "$LOCAL_VERSION" ] && echo "❌ 无法从 package.json 读取版本" && exit 1
|
|
76
|
+
TARGET_VERSION="$LOCAL_VERSION"
|
|
69
77
|
INSTALL_SRC="${PKG_NAME}@${LOCAL_VERSION}"
|
|
70
78
|
shift 1
|
|
71
79
|
;;
|
|
@@ -100,7 +108,7 @@ if [ -z "$APPID" ] && [ -z "$SECRET" ] && [ -n "$QQBOT_TOKEN" ]; then
|
|
|
100
108
|
SECRET="${QQBOT_TOKEN#*:}"
|
|
101
109
|
fi
|
|
102
110
|
|
|
103
|
-
# 检测 CLI
|
|
111
|
+
# 检测 CLI
|
|
104
112
|
CMD=""
|
|
105
113
|
for name in openclaw clawdbot moltbot; do
|
|
106
114
|
command -v "$name" &>/dev/null && CMD="$name" && break
|
|
@@ -110,91 +118,163 @@ done
|
|
|
110
118
|
EXTENSIONS_DIR="$HOME/.$CMD/extensions"
|
|
111
119
|
|
|
112
120
|
echo "==========================================="
|
|
113
|
-
echo " qqbot
|
|
121
|
+
echo " qqbot 升级: $INSTALL_SRC"
|
|
114
122
|
echo "==========================================="
|
|
115
123
|
echo ""
|
|
116
124
|
|
|
117
|
-
#
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
125
|
+
# 记录升级前的版本
|
|
126
|
+
OLD_VERSION=""
|
|
127
|
+
OLD_PKG="$EXTENSIONS_DIR/$PLUGIN_ID/package.json"
|
|
128
|
+
if [ -f "$OLD_PKG" ]; then
|
|
129
|
+
OLD_VERSION="$(node -e "
|
|
130
|
+
try {
|
|
131
|
+
const v = JSON.parse(require('fs').readFileSync('$OLD_PKG', 'utf8')).version;
|
|
132
|
+
if (v) process.stdout.write(String(v));
|
|
133
|
+
} catch {}
|
|
134
|
+
" 2>/dev/null || true)"
|
|
135
|
+
echo " 当前版本: ${OLD_VERSION:-unknown}"
|
|
136
|
+
fi
|
|
137
|
+
|
|
138
|
+
# [1/4] 通过 openclaw 原生指令安装/升级
|
|
139
|
+
echo ""
|
|
140
|
+
echo "[1/4] 安装/升级插件..."
|
|
141
|
+
|
|
142
|
+
# ── 兼容 openclaw 3.23+ 配置严格校验 ──
|
|
143
|
+
# 3.23+ 在 plugins install/update 时会校验整个配置文件,
|
|
144
|
+
# 如果 channels.qqbot 已存在但 qqbot 插件尚未加载,校验会失败。
|
|
145
|
+
# 解决:install/update 前临时移除 channels.qqbot,成功后恢复。
|
|
146
|
+
CONFIG_FILE="$HOME/.$CMD/$CMD.json"
|
|
147
|
+
QQBOT_CHANNEL_BACKUP=""
|
|
148
|
+
if [ -f "$CONFIG_FILE" ]; then
|
|
149
|
+
QQBOT_CHANNEL_BACKUP="$(node -e "
|
|
150
|
+
try {
|
|
151
|
+
const fs = require('fs');
|
|
152
|
+
const cfg = JSON.parse(fs.readFileSync('$CONFIG_FILE', 'utf8'));
|
|
153
|
+
if (cfg.channels && cfg.channels.qqbot) {
|
|
154
|
+
process.stdout.write(JSON.stringify(cfg.channels.qqbot));
|
|
155
|
+
delete cfg.channels.qqbot;
|
|
156
|
+
if (Object.keys(cfg.channels).length === 0) delete cfg.channels;
|
|
157
|
+
fs.writeFileSync('$CONFIG_FILE', JSON.stringify(cfg, null, 4) + '\n');
|
|
158
|
+
}
|
|
159
|
+
} catch {}
|
|
160
|
+
" 2>/dev/null || true)"
|
|
161
|
+
if [ -n "$QQBOT_CHANNEL_BACKUP" ]; then
|
|
162
|
+
echo " [兼容] 临时移除 channels.qqbot 以通过配置校验"
|
|
133
163
|
fi
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
#
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
164
|
+
fi
|
|
165
|
+
|
|
166
|
+
# 恢复 channels.qqbot 的函数(install/update 完成后调用)
|
|
167
|
+
restore_qqbot_channel() {
|
|
168
|
+
if [ -n "$QQBOT_CHANNEL_BACKUP" ] && [ -f "$CONFIG_FILE" ]; then
|
|
169
|
+
node -e "
|
|
170
|
+
try {
|
|
171
|
+
const fs = require('fs');
|
|
172
|
+
const cfg = JSON.parse(fs.readFileSync('$CONFIG_FILE', 'utf8'));
|
|
173
|
+
if (!cfg.channels) cfg.channels = {};
|
|
174
|
+
cfg.channels.qqbot = $QQBOT_CHANNEL_BACKUP;
|
|
175
|
+
fs.writeFileSync('$CONFIG_FILE', JSON.stringify(cfg, null, 4) + '\n');
|
|
176
|
+
} catch {}
|
|
177
|
+
" 2>/dev/null || true
|
|
178
|
+
echo " [兼容] 已恢复 channels.qqbot 配置"
|
|
179
|
+
fi
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
UPGRADE_OK=false
|
|
183
|
+
|
|
184
|
+
# 检测安装状态:同时检查配置记录和磁盘目录
|
|
185
|
+
HAS_INSTALL_RECORD="$(node -e "
|
|
186
|
+
try {
|
|
187
|
+
const fs = require('fs');
|
|
188
|
+
const p = '$HOME/.$CMD/$CMD.json';
|
|
189
|
+
const cfg = JSON.parse(fs.readFileSync(p, 'utf8'));
|
|
190
|
+
const inst = cfg.plugins && cfg.plugins.installs && cfg.plugins.installs['$PLUGIN_ID'];
|
|
191
|
+
if (inst) process.stdout.write('yes');
|
|
192
|
+
} catch {}
|
|
193
|
+
" 2>/dev/null || true)"
|
|
194
|
+
HAS_PLUGIN_DIR=false
|
|
195
|
+
[ -d "$EXTENSIONS_DIR/$PLUGIN_ID" ] && [ -f "$EXTENSIONS_DIR/$PLUGIN_ID/package.json" ] && HAS_PLUGIN_DIR=true
|
|
196
|
+
|
|
197
|
+
# 决策矩阵:
|
|
198
|
+
# 配置有记录 + 目录存在 → update(最佳路径)
|
|
199
|
+
# 配置有记录 + 目录不存在 → 清理残留记录,走 install
|
|
200
|
+
# 配置无记录 + 目录存在 → 删目录,走 install(配置与文件不一致)
|
|
201
|
+
# 配置无记录 + 目录不存在 → 走 install(全新安装)
|
|
202
|
+
#
|
|
203
|
+
# 指定了具体版本(--version/--tag/--self-version)时:
|
|
204
|
+
# update 不支持指定版本,直接走 删除 + install
|
|
205
|
+
|
|
206
|
+
USE_UPDATE=false
|
|
207
|
+
|
|
208
|
+
if [ "$HAS_INSTALL_RECORD" = "yes" ] && [ "$HAS_PLUGIN_DIR" = "true" ] && [ -z "$TARGET_VERSION" ]; then
|
|
209
|
+
# 配置和目录都齐全,且未指定版本 → 走 update
|
|
210
|
+
USE_UPDATE=true
|
|
211
|
+
echo " [检测] 配置记录 ✓ | 插件目录 ✓ | 未指定版本 → 使用 update"
|
|
212
|
+
elif [ "$HAS_INSTALL_RECORD" = "yes" ] && [ "$HAS_PLUGIN_DIR" = "true" ]; then
|
|
213
|
+
echo " [检测] 配置记录 ✓ | 插件目录 ✓ | 指定版本 $TARGET_VERSION → 使用 reinstall"
|
|
214
|
+
elif [ "$HAS_INSTALL_RECORD" = "yes" ]; then
|
|
215
|
+
echo " [检测] 配置记录 ✓ | 插件目录 ✗ → 配置与文件不一致,使用 install"
|
|
216
|
+
elif [ "$HAS_PLUGIN_DIR" = "true" ]; then
|
|
217
|
+
echo " [检测] 配置记录 ✗ | 插件目录 ✓ → 目录残留,清理后 install"
|
|
158
218
|
else
|
|
159
|
-
echo "
|
|
160
|
-
NPM_TMP_CACHE=$(mktemp -d)
|
|
161
|
-
(cd "$STAGING_DIR" && npm install --omit=dev --omit=peer --ignore-scripts --cache="$NPM_TMP_CACHE" --quiet 2>&1) || echo " ⚠️ 依赖安装失败"
|
|
162
|
-
rm -rf "$NPM_TMP_CACHE"
|
|
219
|
+
echo " [检测] 配置记录 ✗ | 插件目录 ✗ → 全新安装"
|
|
163
220
|
fi
|
|
164
221
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
222
|
+
if [ "$USE_UPDATE" = "true" ]; then
|
|
223
|
+
echo " 尝试 update..."
|
|
224
|
+
if $CMD plugins update "$PLUGIN_ID" 2>&1; then
|
|
225
|
+
UPGRADE_OK=true
|
|
226
|
+
echo " ✅ update 成功"
|
|
227
|
+
else
|
|
228
|
+
echo " ⚠️ update 失败,回退到 reinstall..."
|
|
229
|
+
fi
|
|
230
|
+
fi
|
|
231
|
+
|
|
232
|
+
if [ "$UPGRADE_OK" != "true" ]; then
|
|
233
|
+
# 清理旧目录(包含当前插件和历史遗留名称)
|
|
234
|
+
for dir_name in "$PLUGIN_ID" qqbot openclaw-qq; do
|
|
235
|
+
[ -d "$EXTENSIONS_DIR/$dir_name" ] && rm -rf "$EXTENSIONS_DIR/$dir_name" && echo " 已清理: $EXTENSIONS_DIR/$dir_name"
|
|
236
|
+
done
|
|
168
237
|
|
|
169
|
-
|
|
238
|
+
echo " 执行 install: $INSTALL_SRC"
|
|
239
|
+
if $CMD plugins install "$INSTALL_SRC" --pin 2>&1; then
|
|
240
|
+
UPGRADE_OK=true
|
|
241
|
+
echo " ✅ install 成功"
|
|
242
|
+
else
|
|
243
|
+
echo "❌ install 失败"
|
|
244
|
+
restore_qqbot_channel
|
|
245
|
+
echo "QQBOT_NEW_VERSION=unknown"
|
|
246
|
+
echo "QQBOT_REPORT=❌ QQBot 安装失败,请检查网络和 npm registry"
|
|
247
|
+
exit 1
|
|
248
|
+
fi
|
|
249
|
+
fi
|
|
250
|
+
|
|
251
|
+
# install/update 完成,恢复 channels.qqbot
|
|
252
|
+
restore_qqbot_channel
|
|
253
|
+
|
|
254
|
+
# [2/4] 验证安装
|
|
170
255
|
echo ""
|
|
171
|
-
echo "[2/
|
|
256
|
+
echo "[2/4] 验证安装..."
|
|
257
|
+
|
|
258
|
+
PKG_JSON="$EXTENSIONS_DIR/$PLUGIN_ID/package.json"
|
|
259
|
+
if [ -f "$PKG_JSON" ]; then
|
|
260
|
+
NEW_VERSION="$(node -e "process.stdout.write(JSON.parse(require('fs').readFileSync(process.argv[1],'utf8')).version||'')" "$PKG_JSON" 2>/dev/null || true)"
|
|
261
|
+
fi
|
|
262
|
+
|
|
263
|
+
# Preflight 检查
|
|
172
264
|
PREFLIGHT_OK=true
|
|
265
|
+
TARGET_DIR="$EXTENSIONS_DIR/$PLUGIN_ID"
|
|
173
266
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
if [ ! -f "$STAGING_PKG" ]; then
|
|
177
|
-
echo " ❌ 新包缺少 package.json"
|
|
267
|
+
if [ -z "$NEW_VERSION" ]; then
|
|
268
|
+
echo " ❌ 无法读取新版本号"
|
|
178
269
|
PREFLIGHT_OK=false
|
|
179
270
|
else
|
|
180
|
-
|
|
181
|
-
try {
|
|
182
|
-
const v = JSON.parse(require('fs').readFileSync('$STAGING_PKG', 'utf8')).version;
|
|
183
|
-
if (v) process.stdout.write(String(v));
|
|
184
|
-
} catch {}
|
|
185
|
-
" 2>/dev/null || true)"
|
|
186
|
-
if [ -z "$STAGING_VERSION" ]; then
|
|
187
|
-
echo " ❌ package.json 无法解析或缺少 version 字段"
|
|
188
|
-
PREFLIGHT_OK=false
|
|
189
|
-
else
|
|
190
|
-
echo " ✅ 版本号: $STAGING_VERSION"
|
|
191
|
-
fi
|
|
271
|
+
echo " ✅ 版本号: $NEW_VERSION"
|
|
192
272
|
fi
|
|
193
273
|
|
|
194
|
-
#
|
|
274
|
+
# 入口文件
|
|
195
275
|
ENTRY_FILE=""
|
|
196
276
|
for candidate in "dist/index.js" "index.js"; do
|
|
197
|
-
if [ -f "$
|
|
277
|
+
if [ -f "$TARGET_DIR/$candidate" ]; then
|
|
198
278
|
ENTRY_FILE="$candidate"
|
|
199
279
|
break
|
|
200
280
|
fi
|
|
@@ -206,23 +286,23 @@ else
|
|
|
206
286
|
echo " ✅ 入口文件: $ENTRY_FILE"
|
|
207
287
|
fi
|
|
208
288
|
|
|
209
|
-
#
|
|
210
|
-
if [
|
|
211
|
-
|
|
212
|
-
PREFLIGHT_OK=false
|
|
213
|
-
else
|
|
214
|
-
CORE_JS_COUNT=$(find "$STAGING_DIR/dist/src" -name "*.js" -type f 2>/dev/null | wc -l | tr -d ' ')
|
|
289
|
+
# 核心目录
|
|
290
|
+
if [ -d "$TARGET_DIR/dist/src" ]; then
|
|
291
|
+
CORE_JS_COUNT=$(find "$TARGET_DIR/dist/src" -name "*.js" -type f 2>/dev/null | wc -l | tr -d ' ')
|
|
215
292
|
echo " ✅ dist/src/ 包含 ${CORE_JS_COUNT} 个 JS 文件"
|
|
216
293
|
if [ "$CORE_JS_COUNT" -lt 5 ]; then
|
|
217
294
|
echo " ❌ JS 文件数量异常偏少(预期 ≥ 5,实际 ${CORE_JS_COUNT})"
|
|
218
295
|
PREFLIGHT_OK=false
|
|
219
296
|
fi
|
|
297
|
+
else
|
|
298
|
+
echo " ❌ 缺少核心目录 dist/src/"
|
|
299
|
+
PREFLIGHT_OK=false
|
|
220
300
|
fi
|
|
221
301
|
|
|
222
|
-
#
|
|
302
|
+
# 关键模块
|
|
223
303
|
MISSING_MODULES=""
|
|
224
304
|
for module in "dist/src/gateway.js" "dist/src/api.js" "dist/src/admin-resolver.js"; do
|
|
225
|
-
if [ ! -f "$
|
|
305
|
+
if [ ! -f "$TARGET_DIR/$module" ]; then
|
|
226
306
|
MISSING_MODULES="$MISSING_MODULES $module"
|
|
227
307
|
fi
|
|
228
308
|
done
|
|
@@ -233,11 +313,11 @@ else
|
|
|
233
313
|
echo " ✅ 关键模块完整"
|
|
234
314
|
fi
|
|
235
315
|
|
|
236
|
-
#
|
|
237
|
-
if [ -d "$
|
|
316
|
+
# bundled 依赖
|
|
317
|
+
if [ -d "$TARGET_DIR/node_modules" ]; then
|
|
238
318
|
BUNDLED_OK=true
|
|
239
319
|
for dep in "ws" "silk-wasm"; do
|
|
240
|
-
if [ ! -d "$
|
|
320
|
+
if [ ! -d "$TARGET_DIR/node_modules/$dep" ]; then
|
|
241
321
|
echo " ⚠️ bundled 依赖缺失: $dep"
|
|
242
322
|
BUNDLED_OK=false
|
|
243
323
|
fi
|
|
@@ -247,104 +327,20 @@ if [ -d "$STAGING_DIR/node_modules" ]; then
|
|
|
247
327
|
fi
|
|
248
328
|
fi
|
|
249
329
|
|
|
250
|
-
# (f) 如果有旧版本,检查新版本是否合理(不允许降级到 0.x 等异常版本)
|
|
251
|
-
if [ -n "$STAGING_VERSION" ]; then
|
|
252
|
-
STAGING_MAJOR="$(echo "$STAGING_VERSION" | cut -d. -f1)"
|
|
253
|
-
if [ "$STAGING_MAJOR" = "0" ]; then
|
|
254
|
-
echo " ⚠️ 新版本主版本号为 0($STAGING_VERSION),可能不是正式发布版"
|
|
255
|
-
fi
|
|
256
|
-
fi
|
|
257
|
-
|
|
258
|
-
# 检查结果
|
|
259
330
|
if [ "$PREFLIGHT_OK" != "true" ]; then
|
|
260
331
|
echo ""
|
|
261
|
-
echo "❌
|
|
262
|
-
|
|
332
|
+
echo "❌ 验证未通过"
|
|
333
|
+
echo "QQBOT_NEW_VERSION=unknown"
|
|
334
|
+
echo "QQBOT_REPORT=⚠️ QQBot 升级异常,验证未通过"
|
|
263
335
|
exit 1
|
|
264
336
|
fi
|
|
265
|
-
echo " ✅
|
|
337
|
+
echo " ✅ 验证全部通过"
|
|
266
338
|
|
|
267
|
-
# [3/
|
|
268
|
-
# 策略:先把 staging 放到 extensions/ 同级的临时名,再做单次 mv 替换
|
|
339
|
+
# [3/4] 输出结构化信息(供 TS handler 解析)
|
|
269
340
|
echo ""
|
|
270
|
-
echo "[3/
|
|
271
|
-
mkdir -p "$EXTENSIONS_DIR"
|
|
272
|
-
TARGET_DIR="$EXTENSIONS_DIR/openclaw-qqbot"
|
|
273
|
-
OLD_DIR="$(dirname "$EXTENSIONS_DIR")/.qqbot-upgrade-old"
|
|
274
|
-
|
|
275
|
-
rm -rf "$OLD_DIR"
|
|
276
|
-
|
|
277
|
-
# 先把 staging 目录移到 extensions/ 下的临时位置(同文件系统,确保 mv 是 rename 操作)
|
|
278
|
-
STAGING_IN_EXT="$EXTENSIONS_DIR/.openclaw-qqbot-new"
|
|
279
|
-
rm -rf "$STAGING_IN_EXT"
|
|
280
|
-
mv "$STAGING_DIR" "$STAGING_IN_EXT"
|
|
281
|
-
|
|
282
|
-
if [ -d "$TARGET_DIR" ]; then
|
|
283
|
-
# 使用连续两个 mv 但中间零操作,最小化目录不存在的时间窗口
|
|
284
|
-
mv "$TARGET_DIR" "$OLD_DIR" && mv "$STAGING_IN_EXT" "$TARGET_DIR"
|
|
285
|
-
else
|
|
286
|
-
mv "$STAGING_IN_EXT" "$TARGET_DIR"
|
|
287
|
-
fi
|
|
288
|
-
rm -rf "$OLD_DIR"
|
|
289
|
-
|
|
290
|
-
# 清理可能残留的旧版 staging 目录(extensions 内外都清理)
|
|
291
|
-
rm -rf "$EXTENSIONS_DIR/openclaw-qqbot.staging"
|
|
292
|
-
rm -rf "$EXTENSIONS_DIR/.qqbot-upgrade-staging"
|
|
293
|
-
rm -rf "$EXTENSIONS_DIR/.qqbot-upgrade-old"
|
|
294
|
-
|
|
295
|
-
# 同时清理历史遗留的其他目录名
|
|
296
|
-
for dir_name in qqbot openclaw-qq; do
|
|
297
|
-
[ -d "$EXTENSIONS_DIR/$dir_name" ] && rm -rf "$EXTENSIONS_DIR/$dir_name"
|
|
298
|
-
done
|
|
299
|
-
echo " 已安装到: $TARGET_DIR"
|
|
300
|
-
|
|
301
|
-
# 执行 postinstall 脚本创建 openclaw SDK symlink
|
|
302
|
-
# (upgrade-via-npm 是纯文件操作,不走 npm install,所以 postinstall 不会自动触发)
|
|
303
|
-
POSTINSTALL_SCRIPT="$TARGET_DIR/scripts/postinstall-link-sdk.js"
|
|
304
|
-
if [ -f "$POSTINSTALL_SCRIPT" ]; then
|
|
305
|
-
echo " 执行 postinstall: 创建 openclaw SDK symlink..."
|
|
306
|
-
POSTINSTALL_OUTPUT="$(cd "$TARGET_DIR" && node "$POSTINSTALL_SCRIPT" 2>&1)" || true
|
|
307
|
-
[ -n "$POSTINSTALL_OUTPUT" ] && echo " $POSTINSTALL_OUTPUT"
|
|
308
|
-
# 验证 symlink 是否创建成功
|
|
309
|
-
if [ -d "$TARGET_DIR/node_modules/openclaw" ]; then
|
|
310
|
-
echo " ✅ openclaw SDK symlink 已就绪"
|
|
311
|
-
else
|
|
312
|
-
echo " ⚠️ openclaw SDK symlink 未创建,插件可能无法加载"
|
|
313
|
-
echo " 尝试手动创建 symlink..."
|
|
314
|
-
# 手动 fallback:尝试从 CLI 数据目录名推断全局包名
|
|
315
|
-
_CLI_DATA_DIR="$(dirname "$EXTENSIONS_DIR")"
|
|
316
|
-
_CLI_NAME="$(basename "$_CLI_DATA_DIR" | sed 's/^\.//')"
|
|
317
|
-
_GLOBAL_ROOT="$(npm root -g 2>/dev/null || true)"
|
|
318
|
-
if [ -n "$_GLOBAL_ROOT" ] && [ -n "$_CLI_NAME" ] && [ -d "$_GLOBAL_ROOT/$_CLI_NAME" ]; then
|
|
319
|
-
mkdir -p "$TARGET_DIR/node_modules"
|
|
320
|
-
ln -sf "$_GLOBAL_ROOT/$_CLI_NAME" "$TARGET_DIR/node_modules/openclaw" 2>/dev/null && \
|
|
321
|
-
echo " ✅ 手动 symlink 创建成功: -> $_GLOBAL_ROOT/$_CLI_NAME" || \
|
|
322
|
-
echo " ❌ 手动 symlink 创建也失败了"
|
|
323
|
-
else
|
|
324
|
-
echo " ❌ 无法定位全局 $_CLI_NAME 安装路径(npm root -g: $_GLOBAL_ROOT)"
|
|
325
|
-
fi
|
|
326
|
-
fi
|
|
327
|
-
else
|
|
328
|
-
echo " ⚠️ 未找到 postinstall 脚本,跳过 symlink 创建"
|
|
329
|
-
fi
|
|
330
|
-
|
|
331
|
-
# [4/5] 输出新版本号和升级报告(供调用方解析)
|
|
332
|
-
echo ""
|
|
333
|
-
echo "[4/5] 验证安装..."
|
|
334
|
-
NEW_VERSION="$(node -e "
|
|
335
|
-
try {
|
|
336
|
-
const fs = require('fs');
|
|
337
|
-
const path = require('path');
|
|
338
|
-
const p = path.join('$EXTENSIONS_DIR', 'openclaw-qqbot', 'package.json');
|
|
339
|
-
if (fs.existsSync(p)) {
|
|
340
|
-
const v = JSON.parse(fs.readFileSync(p, 'utf8')).version;
|
|
341
|
-
if (v) { process.stdout.write(v); process.exit(0); }
|
|
342
|
-
}
|
|
343
|
-
} catch {}
|
|
344
|
-
" 2>/dev/null || true)"
|
|
341
|
+
echo "[3/4] 升级结果..."
|
|
345
342
|
echo "QQBOT_NEW_VERSION=${NEW_VERSION:-unknown}"
|
|
346
343
|
|
|
347
|
-
# 输出结构化升级报告(QQBOT_REPORT=...),供 TS handler 解析后直接回复用户
|
|
348
344
|
if [ -n "$NEW_VERSION" ] && [ "$NEW_VERSION" != "unknown" ]; then
|
|
349
345
|
echo "QQBOT_REPORT=✅ QQBot 升级完成: v${NEW_VERSION}"
|
|
350
346
|
else
|
|
@@ -353,13 +349,10 @@ fi
|
|
|
353
349
|
|
|
354
350
|
echo ""
|
|
355
351
|
echo "==========================================="
|
|
356
|
-
echo " ✅
|
|
352
|
+
echo " ✅ 安装完成"
|
|
357
353
|
echo "==========================================="
|
|
358
354
|
|
|
359
|
-
# --no-restart
|
|
360
|
-
# 让调用方尽快触发 gateway restart,避免 openclaw 配置轮询
|
|
361
|
-
# 在旧进程中检测到插件变更产生 "plugin not found" warning 刷屏。
|
|
362
|
-
# appid/secret 配置在热更新场景下已经存在,无需重新写入。
|
|
355
|
+
# --no-restart 模式(热更新场景):立即退出,让调用方触发 gateway restart
|
|
363
356
|
if [ "$NO_RESTART" = "true" ]; then
|
|
364
357
|
echo ""
|
|
365
358
|
echo "[跳过重启] --no-restart 已指定,脚本立即退出以便调用方触发 gateway restart"
|
|
@@ -395,10 +388,9 @@ if [ -n "$APPID" ] && [ -n "$SECRET" ]; then
|
|
|
395
388
|
|
|
396
389
|
if [ "$CURRENT_TOKEN" = "$DESIRED_TOKEN" ]; then
|
|
397
390
|
echo " ✅ 当前配置已是目标值,跳过写入"
|
|
398
|
-
elif $CMD channels add --channel qqbot --token "$DESIRED_TOKEN" 2>&1; then
|
|
399
|
-
echo " ✅ 通道配置写入成功"
|
|
400
391
|
else
|
|
401
|
-
|
|
392
|
+
# qqbot 是插件自定义通道,openclaw channels add --channel 不支持,
|
|
393
|
+
# 直接编辑配置文件写入 channels.qqbot
|
|
402
394
|
CONFIG_FILE="$HOME/.$CMD/$CMD.json"
|
|
403
395
|
if [ -f "$CONFIG_FILE" ] && node -e "
|
|
404
396
|
const fs = require('fs');
|
|
@@ -409,10 +401,10 @@ if [ -n "$APPID" ] && [ -n "$SECRET" ]; then
|
|
|
409
401
|
cfg.channels.qqbot.clientSecret = '$SECRET';
|
|
410
402
|
fs.writeFileSync('$CONFIG_FILE', JSON.stringify(cfg, null, 4) + '\n');
|
|
411
403
|
" 2>&1; then
|
|
412
|
-
echo " ✅
|
|
404
|
+
echo " ✅ 通道配置写入成功"
|
|
413
405
|
else
|
|
414
|
-
echo " ❌
|
|
415
|
-
echo "
|
|
406
|
+
echo " ❌ 配置写入失败,请手动编辑 $CONFIG_FILE 添加 channels.qqbot:"
|
|
407
|
+
echo " { \"channels\": { \"qqbot\": { \"appId\": \"$APPID\", \"clientSecret\": \"...\" } } }"
|
|
416
408
|
fi
|
|
417
409
|
fi
|
|
418
410
|
elif [ -n "$APPID" ] || [ -n "$SECRET" ]; then
|
|
@@ -420,11 +412,10 @@ elif [ -n "$APPID" ] || [ -n "$SECRET" ]; then
|
|
|
420
412
|
echo "⚠️ --appid 和 --secret 必须同时提供"
|
|
421
413
|
fi
|
|
422
414
|
|
|
423
|
-
# [
|
|
415
|
+
# [4/4] 重启 gateway 使新版本生效
|
|
424
416
|
echo ""
|
|
425
417
|
|
|
426
418
|
# 手动升级场景:提前写入 startup-marker,阻止重启后 bot 重复推送升级通知
|
|
427
|
-
# (控制台已打印同款提示语,无需 bot 再发一次)
|
|
428
419
|
if [ -n "$NEW_VERSION" ] && [ "$NEW_VERSION" != "unknown" ]; then
|
|
429
420
|
MARKER_DIR="$HOME/.openclaw/qqbot/data"
|
|
430
421
|
mkdir -p "$MARKER_DIR"
|
|
@@ -436,7 +427,6 @@ fi
|
|
|
436
427
|
echo "[重启] 重启 gateway 使新版本生效..."
|
|
437
428
|
if $CMD gateway restart 2>&1; then
|
|
438
429
|
echo " ✅ gateway 已重启"
|
|
439
|
-
# 打印与 bot 通知同款的更新提示语(手动升级场景无需通过 bot 推送)
|
|
440
430
|
echo ""
|
|
441
431
|
if [ -n "$NEW_VERSION" ] && [ "$NEW_VERSION" != "unknown" ]; then
|
|
442
432
|
echo "🎉 QQBot 插件已更新至 v${NEW_VERSION},在线等候你的吩咐。"
|
|
@@ -1,307 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
|
|
3
|
-
# qqbot 测试脚本:自由切换不同的 QQBot npm 包
|
|
4
|
-
#
|
|
5
|
-
# 支持从任意 npm 包安装指定版本到 openclaw extensions 目录。
|
|
6
|
-
# 可用于在不同包之间切换测试,如 @sliverp/qqbot、@tencent-connect/openclaw-qqbot 等。
|
|
7
|
-
#
|
|
8
|
-
# 用法:
|
|
9
|
-
# upgrade-via-alt-pkg.sh --pkg <包名> --version <version> # 指定包+版本
|
|
10
|
-
# upgrade-via-alt-pkg.sh --pkg <包名> # 指定包,安装 latest
|
|
11
|
-
# upgrade-via-alt-pkg.sh --appid <appid> --secret <secret> # 首次安装时配置
|
|
12
|
-
# upgrade-via-alt-pkg.sh --no-restart # 只做文件替换,不重启
|
|
13
|
-
#
|
|
14
|
-
# 示例:
|
|
15
|
-
# bash scripts/upgrade-via-alt-pkg.sh --pkg @sliverp/qqbot --version 1.5.1
|
|
16
|
-
# bash scripts/upgrade-via-alt-pkg.sh --pkg @sliverp/qqbot --version 1.5.4
|
|
17
|
-
# bash scripts/upgrade-via-alt-pkg.sh --pkg @tencent-connect/openclaw-qqbot --version 1.6.4
|
|
18
|
-
# bash scripts/upgrade-via-alt-pkg.sh --pkg @sliverp/qqbot
|
|
19
|
-
# bash scripts/upgrade-via-alt-pkg.sh --pkg @sliverp/qqbot --version 1.5.4 --appid 12345 --secret abc123
|
|
20
|
-
|
|
21
|
-
set -eo pipefail
|
|
22
|
-
|
|
23
|
-
PKG_NAME=""
|
|
24
|
-
VERSION=""
|
|
25
|
-
INSTALL_SRC=""
|
|
26
|
-
APPID=""
|
|
27
|
-
SECRET=""
|
|
28
|
-
NO_RESTART=false
|
|
29
|
-
|
|
30
|
-
print_usage() {
|
|
31
|
-
echo "用法:"
|
|
32
|
-
echo " upgrade-via-alt-pkg.sh --pkg <包名> --version <版本号>"
|
|
33
|
-
echo " upgrade-via-alt-pkg.sh --pkg <包名> # 安装 latest"
|
|
34
|
-
echo ""
|
|
35
|
-
echo "选项:"
|
|
36
|
-
echo " --pkg <name> npm 包名(必填,如 @sliverp/qqbot、@tencent-connect/openclaw-qqbot)"
|
|
37
|
-
echo " --version <version> 指定版本号(如 1.5.1, 1.5.4, 1.6.4)"
|
|
38
|
-
echo " --appid <appid> QQ机器人 appid(首次安装时必填)"
|
|
39
|
-
echo " --secret <secret> QQ机器人 secret(首次安装时必填)"
|
|
40
|
-
echo " --no-restart 只做文件替换,不重启 gateway"
|
|
41
|
-
echo " -h, --help 显示帮助信息"
|
|
42
|
-
echo ""
|
|
43
|
-
echo "环境变量:"
|
|
44
|
-
echo " QQBOT_APPID QQ机器人 appid"
|
|
45
|
-
echo " QQBOT_SECRET QQ机器人 secret"
|
|
46
|
-
echo " QQBOT_TOKEN QQ机器人 token (appid:secret)"
|
|
47
|
-
echo ""
|
|
48
|
-
echo "示例:"
|
|
49
|
-
echo " # 从 @sliverp/qqbot 包安装 v1.5.1"
|
|
50
|
-
echo " bash scripts/upgrade-via-alt-pkg.sh --pkg @sliverp/qqbot --version 1.5.1"
|
|
51
|
-
echo ""
|
|
52
|
-
echo " # 从 @sliverp/qqbot 包安装 v1.5.4"
|
|
53
|
-
echo " bash scripts/upgrade-via-alt-pkg.sh --pkg @sliverp/qqbot --version 1.5.4"
|
|
54
|
-
echo ""
|
|
55
|
-
echo " # 从官方包安装 v1.6.4"
|
|
56
|
-
echo " bash scripts/upgrade-via-alt-pkg.sh --pkg @tencent-connect/openclaw-qqbot --version 1.6.4"
|
|
57
|
-
echo ""
|
|
58
|
-
echo " # 切回 @sliverp/qqbot 包的 latest"
|
|
59
|
-
echo " bash scripts/upgrade-via-alt-pkg.sh --pkg @sliverp/qqbot"
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
while [[ $# -gt 0 ]]; do
|
|
63
|
-
case "$1" in
|
|
64
|
-
--pkg|--package)
|
|
65
|
-
[ -z "$2" ] && echo "❌ --pkg 需要参数" && exit 1
|
|
66
|
-
PKG_NAME="$2"
|
|
67
|
-
shift 2
|
|
68
|
-
;;
|
|
69
|
-
--version)
|
|
70
|
-
[ -z "$2" ] && echo "❌ --version 需要参数" && exit 1
|
|
71
|
-
VERSION="$2"
|
|
72
|
-
shift 2
|
|
73
|
-
;;
|
|
74
|
-
--tag)
|
|
75
|
-
[ -z "$2" ] && echo "❌ --tag 需要参数" && exit 1
|
|
76
|
-
VERSION="$2"
|
|
77
|
-
shift 2
|
|
78
|
-
;;
|
|
79
|
-
--appid)
|
|
80
|
-
[ -z "$2" ] && echo "❌ --appid 需要参数" && exit 1
|
|
81
|
-
APPID="$2"
|
|
82
|
-
shift 2
|
|
83
|
-
;;
|
|
84
|
-
--secret)
|
|
85
|
-
[ -z "$2" ] && echo "❌ --secret 需要参数" && exit 1
|
|
86
|
-
SECRET="$2"
|
|
87
|
-
shift 2
|
|
88
|
-
;;
|
|
89
|
-
--no-restart)
|
|
90
|
-
NO_RESTART=true
|
|
91
|
-
shift 1
|
|
92
|
-
;;
|
|
93
|
-
-h|--help)
|
|
94
|
-
print_usage
|
|
95
|
-
exit 0
|
|
96
|
-
;;
|
|
97
|
-
*) echo "未知选项: $1"; print_usage; exit 1 ;;
|
|
98
|
-
esac
|
|
99
|
-
done
|
|
100
|
-
|
|
101
|
-
# --pkg 必填
|
|
102
|
-
if [ -z "$PKG_NAME" ]; then
|
|
103
|
-
echo "❌ 必须指定 --pkg 参数"
|
|
104
|
-
echo ""
|
|
105
|
-
print_usage
|
|
106
|
-
exit 1
|
|
107
|
-
fi
|
|
108
|
-
|
|
109
|
-
if [ -n "$VERSION" ]; then
|
|
110
|
-
INSTALL_SRC="${PKG_NAME}@${VERSION}"
|
|
111
|
-
else
|
|
112
|
-
INSTALL_SRC="${PKG_NAME}@latest"
|
|
113
|
-
fi
|
|
114
|
-
|
|
115
|
-
# 环境变量 fallback
|
|
116
|
-
APPID="${APPID:-$QQBOT_APPID}"
|
|
117
|
-
SECRET="${SECRET:-$QQBOT_SECRET}"
|
|
118
|
-
if [ -z "$APPID" ] && [ -z "$SECRET" ] && [ -n "$QQBOT_TOKEN" ]; then
|
|
119
|
-
APPID="${QQBOT_TOKEN%%:*}"
|
|
120
|
-
SECRET="${QQBOT_TOKEN#*:}"
|
|
121
|
-
fi
|
|
122
|
-
|
|
123
|
-
# 检测 CLI(仅用于确定 extensions 目录路径)
|
|
124
|
-
CMD=""
|
|
125
|
-
for name in openclaw clawdbot moltbot; do
|
|
126
|
-
command -v "$name" &>/dev/null && CMD="$name" && break
|
|
127
|
-
done
|
|
128
|
-
[ -z "$CMD" ] && echo "❌ 未找到 openclaw / clawdbot / moltbot" && exit 1
|
|
129
|
-
|
|
130
|
-
EXTENSIONS_DIR="$HOME/.$CMD/extensions"
|
|
131
|
-
|
|
132
|
-
echo "==========================================="
|
|
133
|
-
echo " qqbot 测试升级: $INSTALL_SRC"
|
|
134
|
-
echo "==========================================="
|
|
135
|
-
echo ""
|
|
136
|
-
|
|
137
|
-
# [1/3] 下载并安装新版本到临时目录
|
|
138
|
-
echo "[1/3] 下载新版本..."
|
|
139
|
-
TMPDIR_PACK=$(mktemp -d)
|
|
140
|
-
EXTRACT_DIR=$(mktemp -d)
|
|
141
|
-
trap "rm -rf '$TMPDIR_PACK' '$EXTRACT_DIR'" EXIT
|
|
142
|
-
|
|
143
|
-
cd "$TMPDIR_PACK"
|
|
144
|
-
# 多 registry fallback:npmjs.org → npmmirror(国内镜像)→ 默认 registry
|
|
145
|
-
PACK_OK=false
|
|
146
|
-
for _registry in "https://registry.npmjs.org/" "https://registry.npmmirror.com/" ""; do
|
|
147
|
-
if [ -n "$_registry" ]; then
|
|
148
|
-
echo " 尝试 registry: $_registry"
|
|
149
|
-
npm pack "$INSTALL_SRC" --registry "$_registry" --quiet 2>&1 && PACK_OK=true && break
|
|
150
|
-
else
|
|
151
|
-
echo " 尝试默认 registry..."
|
|
152
|
-
npm pack "$INSTALL_SRC" --quiet 2>&1 && PACK_OK=true && break
|
|
153
|
-
fi
|
|
154
|
-
done
|
|
155
|
-
$PACK_OK || { echo "❌ npm pack 失败(所有 registry 均不可用)"; exit 1; }
|
|
156
|
-
TGZ_FILE=$(ls -1 *.tgz 2>/dev/null | head -1)
|
|
157
|
-
[ -z "$TGZ_FILE" ] && echo "❌ 未找到下载的 tgz 文件" && exit 1
|
|
158
|
-
echo " 已下载: $TGZ_FILE"
|
|
159
|
-
|
|
160
|
-
tar xzf "$TGZ_FILE" -C "$EXTRACT_DIR"
|
|
161
|
-
PACKAGE_DIR="$EXTRACT_DIR/package"
|
|
162
|
-
[ ! -d "$PACKAGE_DIR" ] && echo "❌ 解压失败,未找到 package 目录" && exit 1
|
|
163
|
-
|
|
164
|
-
# 准备 staging 目录
|
|
165
|
-
STAGING_DIR="$(dirname "$EXTENSIONS_DIR")/.qqbot-upgrade-staging"
|
|
166
|
-
rm -rf "$STAGING_DIR"
|
|
167
|
-
mkdir -p "$STAGING_DIR"
|
|
168
|
-
cp -R "$PACKAGE_DIR/." "$STAGING_DIR/"
|
|
169
|
-
|
|
170
|
-
# 依赖处理
|
|
171
|
-
if [ -d "$STAGING_DIR/node_modules" ]; then
|
|
172
|
-
BUNDLED_COUNT=$(find "$STAGING_DIR/node_modules" -mindepth 1 -maxdepth 2 -type d | wc -l | tr -d ' ')
|
|
173
|
-
echo " bundled 依赖已就绪(${BUNDLED_COUNT} 个包)"
|
|
174
|
-
else
|
|
175
|
-
echo " ⚠️ 未找到 bundled node_modules,尝试安装依赖..."
|
|
176
|
-
NPM_TMP_CACHE=$(mktemp -d)
|
|
177
|
-
(cd "$STAGING_DIR" && npm install --omit=dev --omit=peer --ignore-scripts --cache="$NPM_TMP_CACHE" --quiet 2>&1) || echo " ⚠️ 依赖安装失败"
|
|
178
|
-
rm -rf "$NPM_TMP_CACHE"
|
|
179
|
-
fi
|
|
180
|
-
|
|
181
|
-
# 清理下载临时文件
|
|
182
|
-
rm -rf "$TMPDIR_PACK" "$EXTRACT_DIR"
|
|
183
|
-
cd "$HOME"
|
|
184
|
-
|
|
185
|
-
# [2/3] 原子替换插件目录
|
|
186
|
-
echo ""
|
|
187
|
-
echo "[2/3] 原子替换插件目录..."
|
|
188
|
-
TARGET_DIR="$EXTENSIONS_DIR/openclaw-qqbot"
|
|
189
|
-
OLD_DIR="$(dirname "$EXTENSIONS_DIR")/.qqbot-upgrade-old"
|
|
190
|
-
|
|
191
|
-
rm -rf "$OLD_DIR"
|
|
192
|
-
|
|
193
|
-
STAGING_IN_EXT="$EXTENSIONS_DIR/.openclaw-qqbot-new"
|
|
194
|
-
rm -rf "$STAGING_IN_EXT"
|
|
195
|
-
mv "$STAGING_DIR" "$STAGING_IN_EXT"
|
|
196
|
-
|
|
197
|
-
if [ -d "$TARGET_DIR" ]; then
|
|
198
|
-
mv "$TARGET_DIR" "$OLD_DIR" && mv "$STAGING_IN_EXT" "$TARGET_DIR"
|
|
199
|
-
else
|
|
200
|
-
mv "$STAGING_IN_EXT" "$TARGET_DIR"
|
|
201
|
-
fi
|
|
202
|
-
rm -rf "$OLD_DIR"
|
|
203
|
-
|
|
204
|
-
# 清理可能残留的旧版 staging 目录
|
|
205
|
-
rm -rf "$EXTENSIONS_DIR/openclaw-qqbot.staging"
|
|
206
|
-
rm -rf "$EXTENSIONS_DIR/.qqbot-upgrade-staging"
|
|
207
|
-
rm -rf "$EXTENSIONS_DIR/.qqbot-upgrade-old"
|
|
208
|
-
|
|
209
|
-
# 清理历史遗留的其他目录名
|
|
210
|
-
for dir_name in qqbot openclaw-qq; do
|
|
211
|
-
[ -d "$EXTENSIONS_DIR/$dir_name" ] && rm -rf "$EXTENSIONS_DIR/$dir_name"
|
|
212
|
-
done
|
|
213
|
-
echo " 已安装到: $TARGET_DIR"
|
|
214
|
-
|
|
215
|
-
# [3/3] 输出新版本号和升级报告
|
|
216
|
-
echo ""
|
|
217
|
-
echo "[3/3] 验证安装..."
|
|
218
|
-
NEW_VERSION="$(node -e "
|
|
219
|
-
try {
|
|
220
|
-
const fs = require('fs');
|
|
221
|
-
const path = require('path');
|
|
222
|
-
const p = path.join('$EXTENSIONS_DIR', 'openclaw-qqbot', 'package.json');
|
|
223
|
-
if (fs.existsSync(p)) {
|
|
224
|
-
const v = JSON.parse(fs.readFileSync(p, 'utf8')).version;
|
|
225
|
-
if (v) { process.stdout.write(v); process.exit(0); }
|
|
226
|
-
}
|
|
227
|
-
} catch {}
|
|
228
|
-
" 2>/dev/null || true)"
|
|
229
|
-
echo "QQBOT_NEW_VERSION=${NEW_VERSION:-unknown}"
|
|
230
|
-
|
|
231
|
-
if [ -n "$NEW_VERSION" ] && [ "$NEW_VERSION" != "unknown" ]; then
|
|
232
|
-
echo "QQBOT_REPORT=✅ QQBot 升级完成 ($PKG_NAME): v${NEW_VERSION}"
|
|
233
|
-
else
|
|
234
|
-
echo "QQBOT_REPORT=⚠️ QQBot 升级异常,无法确认新版本"
|
|
235
|
-
fi
|
|
236
|
-
|
|
237
|
-
echo ""
|
|
238
|
-
echo "==========================================="
|
|
239
|
-
echo " ✅ 文件安装完成"
|
|
240
|
-
echo "==========================================="
|
|
241
|
-
|
|
242
|
-
# --no-restart 模式
|
|
243
|
-
if [ "$NO_RESTART" = "true" ]; then
|
|
244
|
-
echo ""
|
|
245
|
-
echo "[跳过重启] --no-restart 已指定,脚本立即退出以便调用方触发 gateway restart"
|
|
246
|
-
exit 0
|
|
247
|
-
fi
|
|
248
|
-
|
|
249
|
-
# [4/4] 配置 appid/secret(仅在提供了参数时执行)
|
|
250
|
-
if [ -n "$APPID" ] && [ -n "$SECRET" ]; then
|
|
251
|
-
echo ""
|
|
252
|
-
echo "[配置] 写入 qqbot 通道配置..."
|
|
253
|
-
DESIRED_TOKEN="${APPID}:${SECRET}"
|
|
254
|
-
|
|
255
|
-
CURRENT_TOKEN=""
|
|
256
|
-
for _app in openclaw clawdbot moltbot; do
|
|
257
|
-
_cfg="$HOME/.$_app/$_app.json"
|
|
258
|
-
if [ -f "$_cfg" ]; then
|
|
259
|
-
CURRENT_TOKEN=$(node -e "
|
|
260
|
-
const cfg = JSON.parse(require('fs').readFileSync('$_cfg', 'utf8'));
|
|
261
|
-
const keys = ['qqbot', 'openclaw-qqbot', 'openclaw-qq'];
|
|
262
|
-
for (const key of keys) {
|
|
263
|
-
const ch = cfg.channels && cfg.channels[key];
|
|
264
|
-
if (!ch) continue;
|
|
265
|
-
if (ch.token) { process.stdout.write(ch.token); process.exit(0); }
|
|
266
|
-
if (ch.appId && ch.clientSecret) { process.stdout.write(ch.appId + ':' + ch.clientSecret); process.exit(0); }
|
|
267
|
-
}
|
|
268
|
-
" 2>/dev/null || true)
|
|
269
|
-
[ -n "$CURRENT_TOKEN" ] && break
|
|
270
|
-
fi
|
|
271
|
-
done
|
|
272
|
-
|
|
273
|
-
if [ "$CURRENT_TOKEN" = "$DESIRED_TOKEN" ]; then
|
|
274
|
-
echo " ✅ 当前配置已是目标值,跳过写入"
|
|
275
|
-
elif $CMD channels add --channel qqbot --token "$DESIRED_TOKEN" 2>&1; then
|
|
276
|
-
echo " ✅ 通道配置写入成功"
|
|
277
|
-
else
|
|
278
|
-
echo " ⚠️ $CMD channels add 失败,尝试直接编辑配置文件..."
|
|
279
|
-
CONFIG_FILE="$HOME/.$CMD/$CMD.json"
|
|
280
|
-
if [ -f "$CONFIG_FILE" ] && node -e "
|
|
281
|
-
const fs = require('fs');
|
|
282
|
-
const cfg = JSON.parse(fs.readFileSync('$CONFIG_FILE', 'utf8'));
|
|
283
|
-
if (!cfg.channels) cfg.channels = {};
|
|
284
|
-
if (!cfg.channels.qqbot) cfg.channels.qqbot = {};
|
|
285
|
-
cfg.channels.qqbot.appId = '$APPID';
|
|
286
|
-
cfg.channels.qqbot.clientSecret = '$SECRET';
|
|
287
|
-
fs.writeFileSync('$CONFIG_FILE', JSON.stringify(cfg, null, 4) + '\n');
|
|
288
|
-
" 2>&1; then
|
|
289
|
-
echo " ✅ 通道配置写入成功(直接编辑配置文件)"
|
|
290
|
-
else
|
|
291
|
-
echo " ❌ 配置写入失败,请手动配置:"
|
|
292
|
-
echo " $CMD channels add --channel qqbot --token \"${APPID}:${SECRET}\""
|
|
293
|
-
fi
|
|
294
|
-
fi
|
|
295
|
-
elif [ -n "$APPID" ] || [ -n "$SECRET" ]; then
|
|
296
|
-
echo ""
|
|
297
|
-
echo "⚠️ --appid 和 --secret 必须同时提供"
|
|
298
|
-
fi
|
|
299
|
-
|
|
300
|
-
# [5/5] 重启 gateway 使新版本生效
|
|
301
|
-
echo ""
|
|
302
|
-
echo "[重启] 重启 gateway 使新版本生效..."
|
|
303
|
-
if $CMD gateway restart 2>&1; then
|
|
304
|
-
echo " ✅ gateway 已重启"
|
|
305
|
-
else
|
|
306
|
-
echo " ⚠️ gateway 重启失败,请手动执行: $CMD gateway restart"
|
|
307
|
-
fi
|