@tencent-connect/openclaw-qqbot 1.6.0 → 1.6.2-alpha.0

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 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.0`
13
+ ### 🚀 Current Version: `v1.6.1`
14
14
 
15
15
  [![License](https://img.shields.io/badge/license-MIT-green)](./LICENSE)
16
16
  [![QQ Bot](https://img.shields.io/badge/QQ_Bot-API_v2-red)](https://bot.q.qq.com/wiki/)
@@ -163,7 +163,7 @@ Measures end-to-end latency from QQ server push to plugin response, broken down
163
163
 
164
164
  > **You**: `/qqbot-version`
165
165
  >
166
- > **QQBot**: 🦞 Framework: OpenClaw 2026.3.13 (61d171a) / 🤖 Plugin: v1.6.0 / 🌟 GitHub repo
166
+ > **QQBot**: 🦞 Framework: OpenClaw 2026.3.13 (61d171a) / 🤖 Plugin: v1.6.1 / 🌟 GitHub repo
167
167
 
168
168
  Shows framework version, plugin version, and a direct link to the official repository.
169
169
 
package/README.zh.md CHANGED
@@ -9,7 +9,7 @@
9
9
 
10
10
  **让你的 AI 助手接入 QQ — 私聊、群聊、富媒体,一个插件全搞定。**
11
11
 
12
- ### 🚀 当前版本: `v1.6.0`
12
+ ### 🚀 当前版本: `v1.6.1`
13
13
 
14
14
  [![License](https://img.shields.io/badge/license-MIT-green)](./LICENSE)
15
15
  [![QQ Bot](https://img.shields.io/badge/QQ_Bot-API_v2-red)](https://bot.q.qq.com/wiki/)
@@ -158,7 +158,7 @@ AI 可直接发送视频,支持本地文件和公网 URL。
158
158
 
159
159
  > **你**:`/qqbot-version`
160
160
  >
161
- > **QQBot**:🦞框架版本:OpenClaw 2026.3.13 (61d171a) / 🤖QQBot 插件版本:v1.6.0 / 🌟官方 GitHub 仓库
161
+ > **QQBot**:🦞框架版本:OpenClaw 2026.3.13 (61d171a) / 🤖QQBot 插件版本:v1.6.1 / 🌟官方 GitHub 仓库
162
162
 
163
163
  一目了然查看框架版本、插件版本,并可直接跳转官方仓库。
164
164
 
@@ -52,7 +52,7 @@ export const qqbotPlugin = {
52
52
  * blockStreaming: true 表示该 Channel 支持块流式
53
53
  * 框架会收集流式响应,然后通过 deliver 回调发送
54
54
  */
55
- blockStreaming: false,
55
+ blockStreaming: true,
56
56
  },
57
57
  reload: { configPrefixes: ["channels.qqbot"] },
58
58
  // CLI onboarding wizard
@@ -207,7 +207,7 @@ export const qqbotPlugin = {
207
207
  deliveryMode: "direct",
208
208
  chunker: chunkText,
209
209
  chunkerMode: "markdown",
210
- textChunkLimit: 2000,
210
+ textChunkLimit: 20000,
211
211
  sendText: async ({ to, text, accountId, replyToId, cfg }) => {
212
212
  console.log(`[qqbot:channel] sendText called — accountId=${accountId}, to=${to}, replyToId=${replyToId}, text.length=${text?.length ?? 0}`);
213
213
  console.log(`[qqbot:channel] sendText text preview: ${text?.slice(0, 100)}${(text?.length ?? 0) > 100 ? "..." : ""}`);
@@ -7,7 +7,7 @@ import { recordKnownUser, flushKnownUsers, listKnownUsers } from "./known-users.
7
7
  import { getQQBotRuntime } from "./runtime.js";
8
8
  import { setRefIndex, getRefIndex, formatRefEntryForAgent, flushRefIndex } from "./ref-index-store.js";
9
9
  import { matchSlashCommand, getPluginVersion } from "./slash-commands.js";
10
- import { triggerUpdateCheck, onUpdateFound, formatUpdateNotice } from "./update-checker.js";
10
+ import { triggerUpdateCheck } from "./update-checker.js";
11
11
  import { startImageServer, isImageServerRunning, downloadFile } from "./image-server.js";
12
12
  import { getImageSize, formatQQBotMarkdownImage, hasQQBotImageSize } from "./utils/image-size.js";
13
13
  import { parseQQBotPayload, encodePayloadForCron, isCronReminderPayload, isMediaPayload } from "./utils/payload.js";
@@ -315,36 +315,8 @@ export async function startGateway(ctx) {
315
315
  log?.info(`[qqbot:${account.accountId}] ${w}`);
316
316
  }
317
317
  }
318
- // 后台版本检查(detached 子进程,零阻塞)
318
+ // 后台版本检查(供 /qqbot-version、/qqbot-upgrade 指令被动查询)
319
319
  triggerUpdateCheck(log);
320
- // 注册新版本通知回调:仅发给管理员,带防抖
321
- let lastUpdateNotifyAt = 0;
322
- const UPDATE_NOTIFY_DEBOUNCE_MS = 5 * 60 * 1000; // 5 分钟内不重复通知
323
- onUpdateFound(async (info) => {
324
- try {
325
- // 防抖:避免短时间内重复推送
326
- const now = Date.now();
327
- if (now - lastUpdateNotifyAt < UPDATE_NOTIFY_DEBOUNCE_MS) {
328
- log?.debug?.(`[qqbot:${account.accountId}] Update notification debounced`);
329
- return;
330
- }
331
- const notice = formatUpdateNotice(info);
332
- if (!notice)
333
- return;
334
- const adminId = resolveAdminOpenId();
335
- if (!adminId) {
336
- log?.debug?.(`[qqbot:${account.accountId}] No admin or known user to send update notification`);
337
- return;
338
- }
339
- const token = await getAccessToken(account.appId, account.clientSecret);
340
- await sendProactiveC2CMessage(token, adminId, notice);
341
- lastUpdateNotifyAt = Date.now();
342
- log?.info(`[qqbot:${account.accountId}] Sent update notification to admin: ${adminId}`);
343
- }
344
- catch (err) {
345
- log?.debug?.(`[qqbot:${account.accountId}] Failed to send update notification to admin: ${err}`);
346
- }
347
- });
348
320
  // 初始化 API 配置(markdown 支持)
349
321
  initApiConfig({
350
322
  markdownSupport: account.markdownSupport,
@@ -12,16 +12,9 @@ export interface UpdateInfo {
12
12
  checkedAt: number;
13
13
  error?: string;
14
14
  }
15
- type UpdateFoundCallback = (info: UpdateInfo) => void;
16
- /**
17
- * 注册新版本发现回调(仅在首次检测到某个新版本时触发一次)
18
- */
19
- export declare function onUpdateFound(cb: UpdateFoundCallback): void;
20
15
  export declare function triggerUpdateCheck(log?: {
21
16
  info: (msg: string) => void;
22
17
  error: (msg: string) => void;
23
18
  debug?: (msg: string) => void;
24
19
  }): void;
25
20
  export declare function getUpdateInfo(): UpdateInfo;
26
- export declare function formatUpdateNotice(info: UpdateInfo): string;
27
- export {};
@@ -24,15 +24,6 @@ let _lastInfo = {
24
24
  checkedAt: 0,
25
25
  };
26
26
  let _checking = false;
27
- /** 已通知过的版本号,避免同一版本重复推送 */
28
- let _notifiedVersion = null;
29
- let _onUpdateFound = null;
30
- /**
31
- * 注册新版本发现回调(仅在首次检测到某个新版本时触发一次)
32
- */
33
- export function onUpdateFound(cb) {
34
- _onUpdateFound = cb;
35
- }
36
27
  export function triggerUpdateCheck(log) {
37
28
  if (_checking)
38
29
  return;
@@ -64,11 +55,6 @@ export function triggerUpdateCheck(log) {
64
55
  _lastInfo = { current: CURRENT_VERSION, latest: compareTarget, hasUpdate, checkedAt: now };
65
56
  if (hasUpdate) {
66
57
  log?.info?.(`[qqbot:update-checker] new version available: ${compareTarget} (current: ${CURRENT_VERSION})`);
67
- // 首次发现该版本时触发回调
68
- if (_onUpdateFound && compareTarget !== _notifiedVersion) {
69
- _notifiedVersion = compareTarget;
70
- _onUpdateFound(_lastInfo);
71
- }
72
58
  }
73
59
  }
74
60
  catch (parseErr) {
@@ -79,11 +65,6 @@ export function triggerUpdateCheck(log) {
79
65
  export function getUpdateInfo() {
80
66
  return { ..._lastInfo };
81
67
  }
82
- export function formatUpdateNotice(info) {
83
- if (!info.hasUpdate || !info.latest)
84
- return "";
85
- return `\u{1f195} 有新版本可用: v${info.latest}(当前 v${info.current})\n使用 /qqbot-upgrade 升级`;
86
- }
87
68
  function compareVersions(a, b) {
88
69
  const parse = (v) => {
89
70
  const clean = v.replace(/^v/, "");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tencent-connect/openclaw-qqbot",
3
- "version": "1.6.0",
3
+ "version": "1.6.2-alpha.0",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -253,3 +253,12 @@ elif [ -n "$APPID" ] || [ -n "$SECRET" ]; then
253
253
  echo ""
254
254
  echo "⚠️ --appid 和 --secret 必须同时提供"
255
255
  fi
256
+
257
+ # [5/5] 重启 gateway 使新版本生效
258
+ echo ""
259
+ echo "[重启] 重启 gateway 使新版本生效..."
260
+ if $CMD gateway restart 2>&1; then
261
+ echo " ✅ gateway 已重启"
262
+ else
263
+ echo " ⚠️ gateway 重启失败,请手动执行: $CMD gateway restart"
264
+ fi
package/src/channel.ts CHANGED
@@ -66,7 +66,7 @@ export const qqbotPlugin: ChannelPlugin<ResolvedQQBotAccount> = {
66
66
  * blockStreaming: true 表示该 Channel 支持块流式
67
67
  * 框架会收集流式响应,然后通过 deliver 回调发送
68
68
  */
69
- blockStreaming: false,
69
+ blockStreaming: true,
70
70
  },
71
71
  reload: { configPrefixes: ["channels.qqbot"] },
72
72
  // CLI onboarding wizard
@@ -232,7 +232,7 @@ export const qqbotPlugin: ChannelPlugin<ResolvedQQBotAccount> = {
232
232
  deliveryMode: "direct",
233
233
  chunker: chunkText,
234
234
  chunkerMode: "markdown",
235
- textChunkLimit: 2000,
235
+ textChunkLimit: 20000,
236
236
  sendText: async ({ to, text, accountId, replyToId, cfg }) => {
237
237
  console.log(`[qqbot:channel] sendText called — accountId=${accountId}, to=${to}, replyToId=${replyToId}, text.length=${text?.length ?? 0}`);
238
238
  console.log(`[qqbot:channel] sendText text preview: ${text?.slice(0, 100)}${(text?.length ?? 0) > 100 ? "..." : ""}`);
package/src/gateway.ts CHANGED
@@ -8,7 +8,7 @@ import { recordKnownUser, flushKnownUsers, listKnownUsers } from "./known-users.
8
8
  import { getQQBotRuntime } from "./runtime.js";
9
9
  import { setRefIndex, getRefIndex, formatRefEntryForAgent, flushRefIndex, type RefAttachmentSummary } from "./ref-index-store.js";
10
10
  import { matchSlashCommand, getPluginVersion, type SlashCommandContext, type SlashCommandFileResult, type QueueSnapshot } from "./slash-commands.js";
11
- import { triggerUpdateCheck, onUpdateFound, formatUpdateNotice } from "./update-checker.js";
11
+ import { triggerUpdateCheck } from "./update-checker.js";
12
12
  import { startImageServer, isImageServerRunning, downloadFile, type ImageServerConfig } from "./image-server.js";
13
13
  import { getImageSize, formatQQBotMarkdownImage, hasQQBotImageSize, DEFAULT_IMAGE_SIZE } from "./utils/image-size.js";
14
14
  import { parseQQBotPayload, encodePayloadForCron, isCronReminderPayload, isMediaPayload, type CronReminderPayload, type MediaPayload } from "./utils/payload.js";
@@ -410,36 +410,9 @@ export async function startGateway(ctx: GatewayContext): Promise<void> {
410
410
  }
411
411
  }
412
412
 
413
- // 后台版本检查(detached 子进程,零阻塞)
413
+ // 后台版本检查(供 /qqbot-version、/qqbot-upgrade 指令被动查询)
414
414
  triggerUpdateCheck(log);
415
415
 
416
- // 注册新版本通知回调:仅发给管理员,带防抖
417
- let lastUpdateNotifyAt = 0;
418
- const UPDATE_NOTIFY_DEBOUNCE_MS = 5 * 60 * 1000; // 5 分钟内不重复通知
419
- onUpdateFound(async (info) => {
420
- try {
421
- // 防抖:避免短时间内重复推送
422
- const now = Date.now();
423
- if (now - lastUpdateNotifyAt < UPDATE_NOTIFY_DEBOUNCE_MS) {
424
- log?.debug?.(`[qqbot:${account.accountId}] Update notification debounced`);
425
- return;
426
- }
427
- const notice = formatUpdateNotice(info);
428
- if (!notice) return;
429
- const adminId = resolveAdminOpenId();
430
- if (!adminId) {
431
- log?.debug?.(`[qqbot:${account.accountId}] No admin or known user to send update notification`);
432
- return;
433
- }
434
- const token = await getAccessToken(account.appId, account.clientSecret);
435
- await sendProactiveC2CMessage(token, adminId, notice);
436
- lastUpdateNotifyAt = Date.now();
437
- log?.info(`[qqbot:${account.accountId}] Sent update notification to admin: ${adminId}`);
438
- } catch (err) {
439
- log?.debug?.(`[qqbot:${account.accountId}] Failed to send update notification to admin: ${err}`);
440
- }
441
- });
442
-
443
416
  // 初始化 API 配置(markdown 支持)
444
417
  initApiConfig({
445
418
  markdownSupport: account.markdownSupport,
@@ -38,19 +38,6 @@ let _lastInfo: UpdateInfo = {
38
38
 
39
39
  let _checking = false;
40
40
 
41
- /** 已通知过的版本号,避免同一版本重复推送 */
42
- let _notifiedVersion: string | null = null;
43
-
44
- type UpdateFoundCallback = (info: UpdateInfo) => void;
45
- let _onUpdateFound: UpdateFoundCallback | null = null;
46
-
47
- /**
48
- * 注册新版本发现回调(仅在首次检测到某个新版本时触发一次)
49
- */
50
- export function onUpdateFound(cb: UpdateFoundCallback): void {
51
- _onUpdateFound = cb;
52
- }
53
-
54
41
  export function triggerUpdateCheck(log?: {
55
42
  info: (msg: string) => void;
56
43
  error: (msg: string) => void;
@@ -90,11 +77,6 @@ export function triggerUpdateCheck(log?: {
90
77
  _lastInfo = { current: CURRENT_VERSION, latest: compareTarget, hasUpdate, checkedAt: now };
91
78
  if (hasUpdate) {
92
79
  log?.info?.(`[qqbot:update-checker] new version available: ${compareTarget} (current: ${CURRENT_VERSION})`);
93
- // 首次发现该版本时触发回调
94
- if (_onUpdateFound && compareTarget !== _notifiedVersion) {
95
- _notifiedVersion = compareTarget;
96
- _onUpdateFound(_lastInfo);
97
- }
98
80
  }
99
81
  } catch (parseErr) {
100
82
  _lastInfo = { current: CURRENT_VERSION, latest: null, hasUpdate: false, checkedAt: now, error: String(parseErr) };
@@ -107,11 +89,6 @@ export function getUpdateInfo(): UpdateInfo {
107
89
  return { ..._lastInfo };
108
90
  }
109
91
 
110
- export function formatUpdateNotice(info: UpdateInfo): string {
111
- if (!info.hasUpdate || !info.latest) return "";
112
- return `\u{1f195} 有新版本可用: v${info.latest}(当前 v${info.current})\n使用 /qqbot-upgrade 升级`;
113
- }
114
-
115
92
  function compareVersions(a: string, b: string): number {
116
93
  const parse = (v: string) => {
117
94
  const clean = v.replace(/^v/, "");