@openclaw/qqbot 2026.5.7 → 2026.5.10-beta.1

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/api.js CHANGED
@@ -1,9 +1,9 @@
1
- import { C as recordMessageReply, E as setOutboundAudioPort, S as getMessageReplyStats, T as OUTBOUND_ERROR_CODES, _ as sendVoice, a as sendText, b as checkMessageReplyLimit, d as buildMediaTarget, f as parseTarget, g as sendVideoMsg, h as sendPhoto, i as sendProactiveMessage, m as sendDocument, n as sendCronMessage, p as resolveOutboundMediaPath, r as sendMedia, v as resolveUserFacingMediaError, w as DEFAULT_MEDIA_SEND_ERROR, x as getMessageReplyConfig, y as MESSAGE_REPLY_LIMIT } from "./outbound-BJfhwrPg.js";
2
- import { a as resolveQQBotAccount, i as resolveDefaultQQBotAccountId, n as applyQQBotAccountConfig, r as listQQBotAccountIds, t as DEFAULT_ACCOUNT_ID } from "./config-D6545NkC.js";
3
- import { t as qqbotPlugin } from "./channel-CC2YO9fj.js";
4
- import { C as debugLog, L as formatErrorMessage, S as debugError, o as getAccessToken } from "./sender-p-B14eLG.js";
5
- import { t as qqbotSetupPlugin } from "./channel.setup-ByCRAe5H.js";
6
- import { r as getFrameworkCommands, t as getRequestContext } from "./request-context-Cjwx7OwW.js";
1
+ import { C as recordMessageReply, E as setOutboundAudioPort, S as getMessageReplyStats, T as OUTBOUND_ERROR_CODES, _ as sendVoice, a as sendText, b as checkMessageReplyLimit, d as buildMediaTarget, f as parseTarget, g as sendVideoMsg, h as sendPhoto, i as sendProactiveMessage, m as sendDocument, n as sendCronMessage, p as resolveOutboundMediaPath, r as sendMedia, v as resolveUserFacingMediaError, w as DEFAULT_MEDIA_SEND_ERROR, x as getMessageReplyConfig, y as MESSAGE_REPLY_LIMIT } from "./outbound-DL154TS6.js";
2
+ import { a as resolveQQBotAccount, i as resolveDefaultQQBotAccountId, n as applyQQBotAccountConfig, r as listQQBotAccountIds, t as DEFAULT_ACCOUNT_ID } from "./config-BNAanXEH.js";
3
+ import { t as qqbotPlugin } from "./channel-Cl-NJpPD.js";
4
+ import { L as formatErrorMessage, S as debugLog, o as getAccessToken, x as debugError } from "./sender-C-TmIFow.js";
5
+ import { t as qqbotSetupPlugin } from "./channel.setup-BDM8y3aD.js";
6
+ import { r as getFrameworkCommands, t as getRequestContext } from "./request-context-Bn63CUkr.js";
7
7
  import { callGatewayTool } from "openclaw/plugin-sdk/agent-harness-runtime";
8
8
  //#region extensions/qqbot/src/engine/tools/channel-api.ts
9
9
  /**
@@ -1,19 +1,22 @@
1
- import { t as asOptionalObjectRecord } from "./string-normalize-Ci6NM5DE.js";
2
- import { l as ensurePlatformAdapter, u as getBridgeLogger } from "./resolve-D_06fV6-.js";
1
+ import { t as asOptionalObjectRecord } from "./string-normalize-BzzzPOeb.js";
2
+ import { l as ensurePlatformAdapter, u as getBridgeLogger } from "./resolve-Cm33TWZp.js";
3
3
  import { a as resolveApprovalTarget } from "./approval-cg0SVahb.js";
4
- import { a as resolveQQBotAccount, n as applyQQBotAccountConfig, t as DEFAULT_ACCOUNT_ID$1 } from "./config-D6545NkC.js";
5
- import { a as resolveQQBotExecApprovalConfig, i as matchesQQBotApprovalAccount, n as isQQBotExecApprovalAuthorizedSender, o as shouldHandleQQBotExecApprovalRequest, r as isQQBotExecApprovalClientEnabled, t as isQQBotExecApprovalApprover } from "./exec-approvals-COUsM6wZ.js";
6
- import { a as qqbotSetupAdapterShared, i as qqbotMeta, n as qqbotSetupWizard, r as qqbotConfigAdapter, t as qqbotChannelConfigSchema } from "./config-schema-DFcjQw73.js";
4
+ import { a as resolveQQBotAccount, n as applyQQBotAccountConfig, t as DEFAULT_ACCOUNT_ID$1 } from "./config-BNAanXEH.js";
5
+ import { a as resolveQQBotExecApprovalConfig, i as matchesQQBotApprovalAccount, n as isQQBotExecApprovalAuthorizedSender, o as shouldHandleQQBotExecApprovalRequest, r as isQQBotExecApprovalClientEnabled, t as isQQBotExecApprovalApprover } from "./exec-approvals-DgO1msIB.js";
6
+ import { a as qqbotSetupAdapterShared, i as qqbotMeta, n as qqbotSetupWizard, r as qqbotConfigAdapter, t as qqbotChannelConfigSchema } from "./config-schema-BTV9NZbt.js";
7
7
  import { n as writeOpenClawConfigThroughRuntime, t as toGatewayAccount } from "./narrowing-BoieBTIU.js";
8
- import { t as getQQBotRuntime } from "./runtime-BJAS3eXW.js";
9
- import { n as normalizeTarget, s as getQQBotDataPath, t as looksLikeQQBotTarget } from "./target-parser-Y0prnrXD.js";
8
+ import { t as getQQBotRuntime } from "./runtime-CHGblcVc.js";
9
+ import { n as normalizeTarget, s as getQQBotDataPath, t as looksLikeQQBotTarget } from "./target-parser-CTNFSKb1.js";
10
10
  import { getExecApprovalReplyMetadata } from "openclaw/plugin-sdk/approval-runtime";
11
+ import { createMessageReceiptFromOutboundResults, defineChannelMessageAdapter } from "openclaw/plugin-sdk/channel-message";
11
12
  import { createChannelApprovalCapability } from "openclaw/plugin-sdk/approval-delivery-runtime";
12
13
  import { createLazyChannelApprovalNativeRuntimeAdapter } from "openclaw/plugin-sdk/approval-handler-adapter-runtime";
13
14
  import { resolveApprovalRequestSessionConversation } from "openclaw/plugin-sdk/approval-native-runtime";
14
15
  import { normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
15
16
  import fs from "node:fs";
17
+ import { replaceFileAtomicSync } from "openclaw/plugin-sdk/security-runtime";
16
18
  import path from "node:path";
19
+ import { loadJsonFile } from "openclaw/plugin-sdk/json-store";
17
20
  //#region extensions/qqbot/src/bridge/approval/capability.ts
18
21
  /**
19
22
  * QQ Bot Approval Capability — entry point.
@@ -153,7 +156,7 @@ function createQQBotApprovalCapability() {
153
156
  },
154
157
  load: async () => {
155
158
  ensurePlatformAdapter();
156
- return (await import("./handler-runtime-Bqm6N0WG.js")).qqbotApprovalNativeRuntime;
159
+ return (await import("./handler-runtime-C9SrM2gR.js")).qqbotApprovalNativeRuntime;
157
160
  }
158
161
  })
159
162
  });
@@ -229,16 +232,17 @@ function saveCredentialBackup(accountId, appId, clientSecret) {
229
232
  if (!appId || !clientSecret) return;
230
233
  try {
231
234
  const backupPath = getCredentialBackupFile(accountId);
232
- fs.mkdirSync(path.dirname(backupPath), { recursive: true });
233
235
  const data = {
234
236
  accountId,
235
237
  appId,
236
238
  clientSecret,
237
239
  savedAt: (/* @__PURE__ */ new Date()).toISOString()
238
240
  };
239
- const tmpPath = `${backupPath}.tmp`;
240
- fs.writeFileSync(tmpPath, `${JSON.stringify(data, null, 2)}\n`, "utf8");
241
- fs.renameSync(tmpPath, backupPath);
241
+ replaceFileAtomicSync({
242
+ filePath: backupPath,
243
+ content: `${JSON.stringify(data, null, 2)}\n`,
244
+ tempPrefix: ".qqbot-credential-backup"
245
+ });
242
246
  } catch {}
243
247
  }
244
248
  /**
@@ -251,23 +255,20 @@ function saveCredentialBackup(accountId, appId, clientSecret) {
251
255
  function loadCredentialBackup(accountId) {
252
256
  try {
253
257
  if (accountId) {
254
- const newPath = getCredentialBackupFile(accountId);
255
- if (fs.existsSync(newPath)) {
256
- const data = JSON.parse(fs.readFileSync(newPath, "utf8"));
257
- if (data?.appId && data.clientSecret) return data;
258
- }
258
+ const data = loadJsonFile(getCredentialBackupFile(accountId));
259
+ if (data?.appId && data.clientSecret) return data;
259
260
  }
260
261
  const legacy = getLegacyCredentialBackupFile();
261
- if (fs.existsSync(legacy)) {
262
- const data = JSON.parse(fs.readFileSync(legacy, "utf8"));
262
+ const data = loadJsonFile(legacy);
263
+ if (data) {
263
264
  if (!data?.appId || !data?.clientSecret) return null;
264
265
  if (accountId && data.accountId !== accountId) return null;
265
266
  if (data.accountId) try {
266
- const backupPath = getCredentialBackupFile(data.accountId);
267
- fs.mkdirSync(path.dirname(backupPath), { recursive: true });
268
- const tmpPath = `${backupPath}.tmp`;
269
- fs.writeFileSync(tmpPath, `${JSON.stringify(data, null, 2)}\n`, "utf8");
270
- fs.renameSync(tmpPath, backupPath);
267
+ replaceFileAtomicSync({
268
+ filePath: getCredentialBackupFile(data.accountId),
269
+ content: `${JSON.stringify(data, null, 2)}\n`,
270
+ tempPrefix: ".qqbot-credential-backup"
271
+ });
271
272
  fs.unlinkSync(legacy);
272
273
  } catch {}
273
274
  return data;
@@ -342,11 +343,99 @@ function clearAccountCredentials(cfg, accountId) {
342
343
  }
343
344
  //#endregion
344
345
  //#region extensions/qqbot/src/channel.ts
345
- let _gatewayModulePromise;
346
+ let gatewayModulePromise;
346
347
  function loadGatewayModule() {
347
- _gatewayModulePromise ??= import("./gateway-Cs3-_on9.js");
348
- return _gatewayModulePromise;
348
+ gatewayModulePromise ??= import("./gateway-OhbnW8Uq.js");
349
+ return gatewayModulePromise;
350
+ }
351
+ function createQQBotSendReceipt(params) {
352
+ const messageId = params.messageId?.trim();
353
+ return createMessageReceiptFromOutboundResults({
354
+ results: messageId ? [{
355
+ channel: "qqbot",
356
+ messageId,
357
+ conversationId: params.target
358
+ }] : [],
359
+ threadId: params.target,
360
+ kind: params.kind
361
+ });
362
+ }
363
+ async function sendQQBotText(params) {
364
+ await loadGatewayModule();
365
+ const account = resolveQQBotAccount(params.cfg, params.accountId);
366
+ const { sendText } = await import("./outbound-DL154TS6.js").then((n) => n.t);
367
+ const result = await sendText({
368
+ to: params.to,
369
+ text: params.text,
370
+ accountId: params.accountId,
371
+ replyToId: params.replyToId,
372
+ account: toGatewayAccount(account)
373
+ });
374
+ return {
375
+ channel: "qqbot",
376
+ messageId: result.messageId ?? "",
377
+ receipt: createQQBotSendReceipt({
378
+ messageId: result.messageId,
379
+ target: params.to,
380
+ kind: "text"
381
+ }),
382
+ meta: result.error ? { error: result.error } : void 0
383
+ };
384
+ }
385
+ async function sendQQBotMedia(params) {
386
+ await loadGatewayModule();
387
+ const account = resolveQQBotAccount(params.cfg, params.accountId);
388
+ const { sendMedia } = await import("./outbound-DL154TS6.js").then((n) => n.t);
389
+ const result = await sendMedia({
390
+ to: params.to,
391
+ text: params.text ?? "",
392
+ mediaUrl: params.mediaUrl ?? "",
393
+ accountId: params.accountId,
394
+ replyToId: params.replyToId,
395
+ account: toGatewayAccount(account)
396
+ });
397
+ return {
398
+ channel: "qqbot",
399
+ messageId: result.messageId ?? "",
400
+ receipt: createQQBotSendReceipt({
401
+ messageId: result.messageId,
402
+ target: params.to,
403
+ kind: "media"
404
+ }),
405
+ meta: result.error ? { error: result.error } : void 0
406
+ };
407
+ }
408
+ function toQQBotMessageSendResult(result) {
409
+ return {
410
+ messageId: result.messageId,
411
+ receipt: result.receipt
412
+ };
349
413
  }
414
+ const qqbotMessageAdapter = defineChannelMessageAdapter({
415
+ id: "qqbot",
416
+ durableFinal: { capabilities: {
417
+ text: true,
418
+ media: true,
419
+ replyTo: true
420
+ } },
421
+ send: {
422
+ text: async (ctx) => toQQBotMessageSendResult(await sendQQBotText({
423
+ cfg: ctx.cfg,
424
+ to: ctx.to,
425
+ text: ctx.text,
426
+ accountId: ctx.accountId,
427
+ replyToId: ctx.replyToId
428
+ })),
429
+ media: async (ctx) => toQQBotMessageSendResult(await sendQQBotMedia({
430
+ cfg: ctx.cfg,
431
+ to: ctx.to,
432
+ text: ctx.text,
433
+ mediaUrl: ctx.mediaUrl,
434
+ accountId: ctx.accountId,
435
+ replyToId: ctx.replyToId
436
+ }))
437
+ }
438
+ });
350
439
  const EXEC_APPROVAL_COMMAND_RE = /\/approve(?:@[^\s]+)?\s+[A-Za-z0-9][A-Za-z0-9._:-]*\s+(?:allow-once|allow-always|always|deny)\b/i;
351
440
  function persistAccountCredentialSnapshot(account) {
352
441
  if (account.appId && account.clientSecret) saveCredentialBackup(account.accountId, account.appId, account.clientSecret);
@@ -389,6 +478,7 @@ const qqbotPlugin = {
389
478
  },
390
479
  setup: { ...qqbotSetupAdapterShared },
391
480
  approvalCapability: getQQBotApprovalCapability(),
481
+ message: qqbotMessageAdapter,
392
482
  messaging: {
393
483
  targetPrefixes: ["qqbot"],
394
484
  /** Normalize common QQ Bot target formats into the canonical qqbot:... form. */
@@ -410,41 +500,21 @@ const qqbotPlugin = {
410
500
  payload,
411
501
  hint
412
502
  }),
413
- sendText: async ({ to, text, accountId, replyToId, cfg }) => {
414
- await loadGatewayModule();
415
- const account = resolveQQBotAccount(cfg, accountId);
416
- const { sendText } = await import("./outbound-BJfhwrPg.js").then((n) => n.t);
417
- const result = await sendText({
418
- to,
419
- text,
420
- accountId,
421
- replyToId,
422
- account: toGatewayAccount(account)
423
- });
424
- return {
425
- channel: "qqbot",
426
- messageId: result.messageId ?? "",
427
- meta: result.error ? { error: result.error } : void 0
428
- };
429
- },
430
- sendMedia: async ({ to, text, mediaUrl, accountId, replyToId, cfg }) => {
431
- await loadGatewayModule();
432
- const account = resolveQQBotAccount(cfg, accountId);
433
- const { sendMedia } = await import("./outbound-BJfhwrPg.js").then((n) => n.t);
434
- const result = await sendMedia({
435
- to,
436
- text: text ?? "",
437
- mediaUrl: mediaUrl ?? "",
438
- accountId,
439
- replyToId,
440
- account: toGatewayAccount(account)
441
- });
442
- return {
443
- channel: "qqbot",
444
- messageId: result.messageId ?? "",
445
- meta: result.error ? { error: result.error } : void 0
446
- };
447
- }
503
+ sendText: async ({ to, text, accountId, replyToId, cfg }) => await sendQQBotText({
504
+ cfg,
505
+ to,
506
+ text,
507
+ accountId,
508
+ replyToId
509
+ }),
510
+ sendMedia: async ({ to, text, mediaUrl, accountId, replyToId, cfg }) => await sendQQBotMedia({
511
+ cfg,
512
+ to,
513
+ text,
514
+ mediaUrl,
515
+ accountId,
516
+ replyToId
517
+ })
448
518
  },
449
519
  gateway: {
450
520
  startAccount: async (ctx) => {
@@ -1,2 +1,2 @@
1
- import { t as qqbotPlugin } from "./channel-CC2YO9fj.js";
1
+ import { t as qqbotPlugin } from "./channel-Cl-NJpPD.js";
2
2
  export { qqbotPlugin };
@@ -1,5 +1,5 @@
1
- import "./resolve-D_06fV6-.js";
2
- import { a as qqbotSetupAdapterShared, i as qqbotMeta, n as qqbotSetupWizard, r as qqbotConfigAdapter, t as qqbotChannelConfigSchema } from "./config-schema-DFcjQw73.js";
1
+ import "./resolve-Cm33TWZp.js";
2
+ import { a as qqbotSetupAdapterShared, i as qqbotMeta, n as qqbotSetupWizard, r as qqbotConfigAdapter, t as qqbotChannelConfigSchema } from "./config-schema-BTV9NZbt.js";
3
3
  //#region extensions/qqbot/src/channel.setup.ts
4
4
  /**
5
5
  * Setup-only QQBot plugin — lightweight subset used during `openclaw onboard`
@@ -1,5 +1,5 @@
1
- import { c as getPlatformAdapter } from "./string-normalize-Ci6NM5DE.js";
2
- import { c as resolveDefaultAccountId, n as applyAccountConfig, o as listAccountIds, s as resolveAccountBase, t as DEFAULT_ACCOUNT_ID$1 } from "./resolve-D_06fV6-.js";
1
+ import { c as getPlatformAdapter } from "./string-normalize-BzzzPOeb.js";
2
+ import { c as resolveDefaultAccountId, n as applyAccountConfig, o as listAccountIds, s as resolveAccountBase, t as DEFAULT_ACCOUNT_ID$1 } from "./resolve-Cm33TWZp.js";
3
3
  import { coerceSecretRef, normalizeSecretInputString } from "openclaw/plugin-sdk/secret-input";
4
4
  import fs from "node:fs";
5
5
  import { resolveDefaultSecretProviderAlias } from "openclaw/plugin-sdk/provider-auth";
@@ -1,12 +1,12 @@
1
- import { n as normalizeLowercaseStringOrEmpty } from "./string-normalize-Ci6NM5DE.js";
2
- import { a as isAccountConfigured, i as formatAllowFrom, n as applyAccountConfig, r as describeAccount } from "./resolve-D_06fV6-.js";
3
- import { a as resolveQQBotAccount, i as resolveDefaultQQBotAccountId, n as applyQQBotAccountConfig, r as listQQBotAccountIds } from "./config-D6545NkC.js";
1
+ import { n as normalizeLowercaseStringOrEmpty } from "./string-normalize-BzzzPOeb.js";
2
+ import { a as isAccountConfigured, i as formatAllowFrom, n as applyAccountConfig, r as describeAccount } from "./resolve-Cm33TWZp.js";
3
+ import { a as resolveQQBotAccount, i as resolveDefaultQQBotAccountId, n as applyQQBotAccountConfig, r as listQQBotAccountIds } from "./config-BNAanXEH.js";
4
4
  import { buildSecretInputSchema } from "openclaw/plugin-sdk/secret-input";
5
5
  import { applyAccountNameToChannelSection, deleteAccountFromConfigSection, setAccountEnabledInConfigSection } from "openclaw/plugin-sdk/core";
6
6
  import { DEFAULT_ACCOUNT_ID, createStandardChannelSetupStatus, setSetupChannelEnabled } from "openclaw/plugin-sdk/setup";
7
7
  import { formatDocsLink } from "openclaw/plugin-sdk/setup-tools";
8
8
  import { AllowFromListSchema, buildChannelConfigSchema } from "openclaw/plugin-sdk/channel-config-schema";
9
- import { z } from "zod";
9
+ import { z } from "openclaw/plugin-sdk/zod";
10
10
  //#region extensions/qqbot/src/engine/config/setup-logic.ts
11
11
  /**
12
12
  * QQBot setup business logic (pure layer).
@@ -1,4 +1,4 @@
1
- import { a as resolveQQBotAccount, r as listQQBotAccountIds } from "./config-D6545NkC.js";
1
+ import { a as resolveQQBotAccount, r as listQQBotAccountIds } from "./config-BNAanXEH.js";
2
2
  import { resolveApprovalRequestChannelAccountId } from "openclaw/plugin-sdk/approval-native-runtime";
3
3
  import { normalizeLowercaseStringOrEmpty, normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
4
4
  import { resolveApprovalApprovers } from "openclaw/plugin-sdk/approval-auth-runtime";