@openclaw/qqbot 2026.5.14-beta.1 → 2026.5.14-beta.2
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 +6 -6
- package/dist/channel-nG7HntSR.js +1102 -0
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel.setup-DWWV_GAa.js → channel.setup-D_8Ryfln.js} +1 -2
- package/dist/{config-DiBiPtf4.js → config-schema-BE5YP0NG.js} +316 -12
- package/dist/{gateway-DEJhmN-p.js → gateway-Bz_nu9BP.js} +5 -8
- package/dist/{handler-runtime-COWL4RMq.js → handler-runtime-DMMHU4NC.js} +3 -3
- package/dist/{outbound-BdQEr78b.js → outbound-DTQUASKu.js} +2 -2
- package/dist/{request-context-Betw4nJr.js → request-context-DiWgzdpn.js} +2 -2
- package/dist/{sender-BeE_CBbN.js → runtime-BFcYWYuk.js} +17 -1
- package/dist/runtime-api.js +1 -1
- package/dist/setup-plugin-api.js +1 -1
- package/package.json +5 -5
- package/dist/channel-BYNY5Nwb.js +0 -606
- package/dist/config-schema-BeJQUheK.js +0 -308
- package/dist/exec-approvals-Deww_EGt.js +0 -238
- package/dist/narrowing-Bj4eMufj.js +0 -25
- package/dist/runtime-B-cqLImu.js +0 -18
- package/dist/target-parser-ByU3srDK.js +0 -245
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as qqbotPlugin } from "./channel-
|
|
1
|
+
import { t as qqbotPlugin } from "./channel-nG7HntSR.js";
|
|
2
2
|
export { qqbotPlugin };
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import "./config-
|
|
2
|
-
import { a as qqbotSetupAdapterShared, i as qqbotMeta, n as qqbotSetupWizard, r as qqbotConfigAdapter, t as qqbotChannelConfigSchema } from "./config-schema-BeJQUheK.js";
|
|
1
|
+
import { a as qqbotSetupAdapterShared, i as qqbotMeta, n as qqbotSetupWizard, r as qqbotConfigAdapter, t as qqbotChannelConfigSchema } from "./config-schema-BE5YP0NG.js";
|
|
3
2
|
//#region extensions/qqbot/src/channel.setup.ts
|
|
4
3
|
/**
|
|
5
4
|
* Setup-only QQBot plugin — lightweight subset used during `openclaw onboard`
|
|
@@ -1,8 +1,13 @@
|
|
|
1
|
-
import { a as normalizeStringifiedOptionalString, c as getPlatformAdapter, d as registerPlatformAdapterFactory, l as hasPlatformAdapter, o as readStringField, r as normalizeOptionalLowercaseString, t as asOptionalObjectRecord, u as registerPlatformAdapter } from "./string-normalize-C46CS-F1.js";
|
|
2
|
-
import { coerceSecretRef, hasConfiguredSecretInput, normalizeResolvedSecretInputString, normalizeSecretInputString } from "openclaw/plugin-sdk/secret-input";
|
|
1
|
+
import { a as normalizeStringifiedOptionalString, c as getPlatformAdapter, d as registerPlatformAdapterFactory, l as hasPlatformAdapter, n as normalizeLowercaseStringOrEmpty, o as readStringField, r as normalizeOptionalLowercaseString, t as asOptionalObjectRecord, u as registerPlatformAdapter } from "./string-normalize-C46CS-F1.js";
|
|
2
|
+
import { buildSecretInputSchema, coerceSecretRef, hasConfiguredSecretInput, normalizeResolvedSecretInputString, normalizeSecretInputString } from "openclaw/plugin-sdk/secret-input";
|
|
3
3
|
import { resolvePreferredOpenClawTmpDir } from "openclaw/plugin-sdk/temp-path";
|
|
4
4
|
import fs from "node:fs";
|
|
5
5
|
import { resolveDefaultSecretProviderAlias } from "openclaw/plugin-sdk/provider-auth";
|
|
6
|
+
import { applyAccountNameToChannelSection, deleteAccountFromConfigSection, setAccountEnabledInConfigSection } from "openclaw/plugin-sdk/core";
|
|
7
|
+
import { DEFAULT_ACCOUNT_ID, createStandardChannelSetupStatus, setSetupChannelEnabled } from "openclaw/plugin-sdk/setup";
|
|
8
|
+
import { formatDocsLink } from "openclaw/plugin-sdk/setup-tools";
|
|
9
|
+
import { AllowFromListSchema, buildChannelConfigSchema } from "openclaw/plugin-sdk/channel-config-schema";
|
|
10
|
+
import { z } from "zod";
|
|
6
11
|
//#region extensions/qqbot/src/bridge/logger.ts
|
|
7
12
|
let _logger = null;
|
|
8
13
|
/** Register the framework logger. Called once in startGateway(). */
|
|
@@ -133,7 +138,7 @@ ensurePlatformAdapter();
|
|
|
133
138
|
* Default account ID, used for the unnamed top-level account.
|
|
134
139
|
* 默认账号 ID,用于顶层配置中未命名的账号。
|
|
135
140
|
*/
|
|
136
|
-
const DEFAULT_ACCOUNT_ID$
|
|
141
|
+
const DEFAULT_ACCOUNT_ID$2 = "default";
|
|
137
142
|
function normalizeAppId(raw) {
|
|
138
143
|
if (typeof raw === "string") return raw.trim();
|
|
139
144
|
if (typeof raw === "number") return String(raw);
|
|
@@ -157,7 +162,7 @@ function readQQBotSection(cfg) {
|
|
|
157
162
|
function listAccountIds(cfg) {
|
|
158
163
|
const ids = /* @__PURE__ */ new Set();
|
|
159
164
|
const qqbot = readQQBotSection(cfg);
|
|
160
|
-
if (qqbot?.appId || process.env.QQBOT_APP_ID) ids.add(DEFAULT_ACCOUNT_ID$
|
|
165
|
+
if (qqbot?.appId || process.env.QQBOT_APP_ID) ids.add(DEFAULT_ACCOUNT_ID$2);
|
|
161
166
|
if (qqbot?.accounts) {
|
|
162
167
|
for (const accountId of Object.keys(qqbot.accounts)) if (qqbot.accounts[accountId]?.appId) ids.add(accountId);
|
|
163
168
|
}
|
|
@@ -171,12 +176,12 @@ function resolveDefaultAccountId(cfg) {
|
|
|
171
176
|
const qqbot = readQQBotSection(cfg);
|
|
172
177
|
const configuredDefaultAccountId = normalizeOptionalLowercaseString(qqbot?.defaultAccount);
|
|
173
178
|
if (configuredDefaultAccountId && (configuredDefaultAccountId === "default" || Boolean(qqbot?.accounts?.[configuredDefaultAccountId]?.appId))) return configuredDefaultAccountId;
|
|
174
|
-
if (qqbot?.appId || process.env.QQBOT_APP_ID) return DEFAULT_ACCOUNT_ID$
|
|
179
|
+
if (qqbot?.appId || process.env.QQBOT_APP_ID) return DEFAULT_ACCOUNT_ID$2;
|
|
175
180
|
if (qqbot?.accounts) {
|
|
176
181
|
const ids = Object.keys(qqbot.accounts);
|
|
177
182
|
if (ids.length > 0) return ids[0];
|
|
178
183
|
}
|
|
179
|
-
return DEFAULT_ACCOUNT_ID$
|
|
184
|
+
return DEFAULT_ACCOUNT_ID$2;
|
|
180
185
|
}
|
|
181
186
|
/**
|
|
182
187
|
* Resolve base account info (without credentials).
|
|
@@ -284,7 +289,7 @@ function formatAllowFrom(allowFrom) {
|
|
|
284
289
|
}
|
|
285
290
|
//#endregion
|
|
286
291
|
//#region extensions/qqbot/src/bridge/config.ts
|
|
287
|
-
const DEFAULT_ACCOUNT_ID = DEFAULT_ACCOUNT_ID$
|
|
292
|
+
const DEFAULT_ACCOUNT_ID$1 = DEFAULT_ACCOUNT_ID$2;
|
|
288
293
|
function assertNotLegacySecretRefMarker(value, path) {
|
|
289
294
|
const normalized = normalizeSecretInputString(value);
|
|
290
295
|
if (!normalized || !/^secretref(?:-env)?:/i.test(normalized)) return;
|
|
@@ -329,13 +334,13 @@ function resolveQQBotAccount(cfg, accountId, opts) {
|
|
|
329
334
|
* fields (allowFrom, streaming, …) often live under `accounts.default`.
|
|
330
335
|
* Merge that slice so runtime sees `config.streaming` etc.
|
|
331
336
|
*/
|
|
332
|
-
const accountConfig = base.accountId === DEFAULT_ACCOUNT_ID ? {
|
|
337
|
+
const accountConfig = base.accountId === DEFAULT_ACCOUNT_ID$1 ? {
|
|
333
338
|
...qqbot,
|
|
334
|
-
...qqbot?.accounts?.[DEFAULT_ACCOUNT_ID]
|
|
339
|
+
...qqbot?.accounts?.[DEFAULT_ACCOUNT_ID$1]
|
|
335
340
|
} : qqbot?.accounts?.[base.accountId] ?? {};
|
|
336
341
|
let clientSecret = "";
|
|
337
342
|
let secretSource = "none";
|
|
338
|
-
const clientSecretPath = base.accountId === DEFAULT_ACCOUNT_ID ? "channels.qqbot.clientSecret" : `channels.qqbot.accounts.${base.accountId}.clientSecret`;
|
|
343
|
+
const clientSecretPath = base.accountId === DEFAULT_ACCOUNT_ID$1 ? "channels.qqbot.clientSecret" : `channels.qqbot.accounts.${base.accountId}.clientSecret`;
|
|
339
344
|
const adapter = getPlatformAdapter();
|
|
340
345
|
if (adapter.hasConfiguredSecret(accountConfig.clientSecret)) {
|
|
341
346
|
clientSecret = opts?.allowUnresolvedSecretRef ? adapter.normalizeSecretInputString(accountConfig.clientSecret) ?? "" : resolveQQBotClientSecretInput({
|
|
@@ -350,7 +355,7 @@ function resolveQQBotAccount(cfg, accountId, opts) {
|
|
|
350
355
|
} catch {
|
|
351
356
|
secretSource = "none";
|
|
352
357
|
}
|
|
353
|
-
else if (process.env.QQBOT_CLIENT_SECRET && base.accountId === DEFAULT_ACCOUNT_ID) {
|
|
358
|
+
else if (process.env.QQBOT_CLIENT_SECRET && base.accountId === DEFAULT_ACCOUNT_ID$1) {
|
|
354
359
|
clientSecret = process.env.QQBOT_CLIENT_SECRET;
|
|
355
360
|
secretSource = "env";
|
|
356
361
|
}
|
|
@@ -371,4 +376,303 @@ function applyQQBotAccountConfig(cfg, accountId, input) {
|
|
|
371
376
|
return applyAccountConfig(cfg, accountId, input);
|
|
372
377
|
}
|
|
373
378
|
//#endregion
|
|
374
|
-
|
|
379
|
+
//#region extensions/qqbot/src/engine/config/setup-logic.ts
|
|
380
|
+
/**
|
|
381
|
+
* QQBot setup business logic (pure layer).
|
|
382
|
+
* QQBot setup 相关纯业务逻辑。
|
|
383
|
+
*
|
|
384
|
+
* Token parsing, input validation, and setup config application.
|
|
385
|
+
* All functions are framework-agnostic and operate on plain objects.
|
|
386
|
+
*/
|
|
387
|
+
/** Parse an inline "appId:clientSecret" token string. */
|
|
388
|
+
function parseInlineToken(token) {
|
|
389
|
+
const colonIdx = token.indexOf(":");
|
|
390
|
+
if (colonIdx <= 0 || colonIdx === token.length - 1) return null;
|
|
391
|
+
const appId = token.slice(0, colonIdx).trim();
|
|
392
|
+
const clientSecret = token.slice(colonIdx + 1).trim();
|
|
393
|
+
if (!appId || !clientSecret) return null;
|
|
394
|
+
return {
|
|
395
|
+
appId,
|
|
396
|
+
clientSecret
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
/** Validate setup input for a QQBot account. Returns an error string or null. */
|
|
400
|
+
function validateSetupInput(accountId, input) {
|
|
401
|
+
if (!input.token && !input.tokenFile && !input.useEnv) return "QQBot requires --token (format: appId:clientSecret) or --use-env";
|
|
402
|
+
if (input.useEnv && accountId !== "default") return "QQBot --use-env only supports the default account";
|
|
403
|
+
if (input.token && !parseInlineToken(input.token)) return "QQBot --token must be in appId:clientSecret format";
|
|
404
|
+
return null;
|
|
405
|
+
}
|
|
406
|
+
/** Apply setup input to account config. Returns updated config. */
|
|
407
|
+
function applySetupAccountConfig(cfg, accountId, input) {
|
|
408
|
+
if (input.useEnv && accountId !== "default") return cfg;
|
|
409
|
+
let appId = "";
|
|
410
|
+
let clientSecret = "";
|
|
411
|
+
if (input.token) {
|
|
412
|
+
const parsed = parseInlineToken(input.token);
|
|
413
|
+
if (!parsed) return cfg;
|
|
414
|
+
appId = parsed.appId;
|
|
415
|
+
clientSecret = parsed.clientSecret;
|
|
416
|
+
}
|
|
417
|
+
if (!appId && !input.tokenFile && !input.useEnv) return cfg;
|
|
418
|
+
return applyAccountConfig(cfg, accountId, {
|
|
419
|
+
appId,
|
|
420
|
+
clientSecret,
|
|
421
|
+
clientSecretFile: input.tokenFile,
|
|
422
|
+
name: input.name
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
//#endregion
|
|
426
|
+
//#region extensions/qqbot/src/bridge/config-shared.ts
|
|
427
|
+
const qqbotMeta = {
|
|
428
|
+
id: "qqbot",
|
|
429
|
+
label: "QQ Bot",
|
|
430
|
+
selectionLabel: "QQ Bot (Bot API)",
|
|
431
|
+
docsPath: "/channels/qqbot",
|
|
432
|
+
blurb: "Connect to QQ via official QQ Bot API",
|
|
433
|
+
order: 50
|
|
434
|
+
};
|
|
435
|
+
function validateQQBotSetupInput(params) {
|
|
436
|
+
return validateSetupInput(params.accountId, params.input);
|
|
437
|
+
}
|
|
438
|
+
function applyQQBotSetupAccountConfig(params) {
|
|
439
|
+
return applySetupAccountConfig(params.cfg, params.accountId, params.input);
|
|
440
|
+
}
|
|
441
|
+
function isQQBotConfigured(account) {
|
|
442
|
+
return isAccountConfigured(account);
|
|
443
|
+
}
|
|
444
|
+
function describeQQBotAccount(account) {
|
|
445
|
+
return describeAccount(account);
|
|
446
|
+
}
|
|
447
|
+
function formatQQBotAllowFrom(params) {
|
|
448
|
+
return formatAllowFrom(params.allowFrom);
|
|
449
|
+
}
|
|
450
|
+
const qqbotConfigAdapter = {
|
|
451
|
+
listAccountIds: (cfg) => listQQBotAccountIds(cfg),
|
|
452
|
+
resolveAccount: (cfg, accountId) => resolveQQBotAccount(cfg, accountId, { allowUnresolvedSecretRef: true }),
|
|
453
|
+
defaultAccountId: (cfg) => resolveDefaultQQBotAccountId(cfg),
|
|
454
|
+
setAccountEnabled: ({ cfg, accountId, enabled }) => setAccountEnabledInConfigSection({
|
|
455
|
+
cfg,
|
|
456
|
+
sectionKey: "qqbot",
|
|
457
|
+
accountId,
|
|
458
|
+
enabled,
|
|
459
|
+
allowTopLevel: true
|
|
460
|
+
}),
|
|
461
|
+
deleteAccount: ({ cfg, accountId }) => deleteAccountFromConfigSection({
|
|
462
|
+
cfg,
|
|
463
|
+
sectionKey: "qqbot",
|
|
464
|
+
accountId,
|
|
465
|
+
clearBaseFields: [
|
|
466
|
+
"appId",
|
|
467
|
+
"clientSecret",
|
|
468
|
+
"clientSecretFile",
|
|
469
|
+
"name"
|
|
470
|
+
]
|
|
471
|
+
}),
|
|
472
|
+
isConfigured: isQQBotConfigured,
|
|
473
|
+
describeAccount: describeQQBotAccount,
|
|
474
|
+
resolveAllowFrom: ({ cfg, accountId }) => resolveQQBotAccount(cfg, accountId, { allowUnresolvedSecretRef: true }).config?.allowFrom,
|
|
475
|
+
formatAllowFrom: ({ allowFrom }) => formatQQBotAllowFrom({ allowFrom })
|
|
476
|
+
};
|
|
477
|
+
const qqbotSetupAdapterShared = {
|
|
478
|
+
resolveAccountId: ({ cfg, accountId }) => normalizeLowercaseStringOrEmpty(accountId) || resolveDefaultQQBotAccountId(cfg),
|
|
479
|
+
applyAccountName: ({ cfg, accountId, name }) => applyAccountNameToChannelSection({
|
|
480
|
+
cfg,
|
|
481
|
+
channelKey: "qqbot",
|
|
482
|
+
accountId,
|
|
483
|
+
name
|
|
484
|
+
}),
|
|
485
|
+
validateInput: ({ accountId, input }) => validateQQBotSetupInput({
|
|
486
|
+
accountId,
|
|
487
|
+
input
|
|
488
|
+
}),
|
|
489
|
+
applyAccountConfig: ({ cfg, accountId, input }) => applyQQBotSetupAccountConfig({
|
|
490
|
+
cfg,
|
|
491
|
+
accountId,
|
|
492
|
+
input
|
|
493
|
+
})
|
|
494
|
+
};
|
|
495
|
+
//#endregion
|
|
496
|
+
//#region extensions/qqbot/src/bridge/setup/finalize.ts
|
|
497
|
+
function isQQBotAccountConfigured(cfg, accountId) {
|
|
498
|
+
const account = resolveQQBotAccount(cfg, accountId, { allowUnresolvedSecretRef: true });
|
|
499
|
+
return Boolean(account.appId && account.clientSecret);
|
|
500
|
+
}
|
|
501
|
+
async function linkViaQrCode(params) {
|
|
502
|
+
try {
|
|
503
|
+
const { qrConnect } = await import("@tencent-connect/qqbot-connector");
|
|
504
|
+
const accounts = await qrConnect({ source: "openclaw" });
|
|
505
|
+
if (accounts.length === 0) {
|
|
506
|
+
await params.prompter.note("未获取到任何 QQ Bot 账号信息。", "QQ Bot");
|
|
507
|
+
return params.cfg;
|
|
508
|
+
}
|
|
509
|
+
let next = params.cfg;
|
|
510
|
+
for (let i = 0; i < accounts.length; i++) {
|
|
511
|
+
const { appId, appSecret } = accounts[i];
|
|
512
|
+
const targetAccountId = i === 0 ? params.accountId : appId;
|
|
513
|
+
next = applyQQBotAccountConfig(next, targetAccountId, {
|
|
514
|
+
appId,
|
|
515
|
+
clientSecret: appSecret
|
|
516
|
+
});
|
|
517
|
+
}
|
|
518
|
+
if (accounts.length === 1) params.runtime.log(`✔ QQ Bot 绑定成功!(AppID: ${accounts[0].appId})`);
|
|
519
|
+
else {
|
|
520
|
+
const idList = accounts.map((a) => a.appId).join(", ");
|
|
521
|
+
params.runtime.log(`✔ ${accounts.length} 个 QQ Bot 绑定成功!(AppID: ${idList})`);
|
|
522
|
+
}
|
|
523
|
+
return next;
|
|
524
|
+
} catch (error) {
|
|
525
|
+
params.runtime.error(`QQ Bot 绑定失败: ${String(error)}`);
|
|
526
|
+
await params.prompter.note(["绑定失败,您可以稍后手动配置。", `文档: ${formatDocsLink("/channels/qqbot", "qqbot")}`].join("\n"), "QQ Bot");
|
|
527
|
+
return params.cfg;
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
async function linkViaManualInput(params) {
|
|
531
|
+
const appId = await params.prompter.text({
|
|
532
|
+
message: "请输入 QQ Bot AppID",
|
|
533
|
+
validate: (value) => value.trim() ? void 0 : "AppID 不能为空"
|
|
534
|
+
});
|
|
535
|
+
const appSecret = await params.prompter.text({
|
|
536
|
+
message: "请输入 QQ Bot AppSecret",
|
|
537
|
+
validate: (value) => value.trim() ? void 0 : "AppSecret 不能为空"
|
|
538
|
+
});
|
|
539
|
+
const next = applyQQBotAccountConfig(params.cfg, params.accountId, {
|
|
540
|
+
appId: appId.trim(),
|
|
541
|
+
clientSecret: appSecret.trim()
|
|
542
|
+
});
|
|
543
|
+
await params.prompter.note("✔ QQ Bot 配置完成!", "QQ Bot");
|
|
544
|
+
return next;
|
|
545
|
+
}
|
|
546
|
+
async function finalizeQQBotSetup(params) {
|
|
547
|
+
const accountId = params.accountId.trim() || DEFAULT_ACCOUNT_ID;
|
|
548
|
+
let next = params.cfg;
|
|
549
|
+
const configured = isQQBotAccountConfigured(next, accountId);
|
|
550
|
+
const mode = await params.prompter.select({
|
|
551
|
+
message: configured ? "QQ 已绑定,选择操作" : "选择 QQ 绑定方式",
|
|
552
|
+
options: [
|
|
553
|
+
{
|
|
554
|
+
value: "qr",
|
|
555
|
+
label: "扫码绑定(推荐)",
|
|
556
|
+
hint: "使用 QQ 扫描二维码自动完成绑定"
|
|
557
|
+
},
|
|
558
|
+
{
|
|
559
|
+
value: "manual",
|
|
560
|
+
label: "手动输入 QQ Bot AppID 和 AppSecret",
|
|
561
|
+
hint: "需到 QQ 开放平台 q.qq.com 查看"
|
|
562
|
+
},
|
|
563
|
+
{
|
|
564
|
+
value: "skip",
|
|
565
|
+
label: configured ? "保持当前配置" : "稍后配置"
|
|
566
|
+
}
|
|
567
|
+
]
|
|
568
|
+
});
|
|
569
|
+
if (mode === "qr") next = await linkViaQrCode({
|
|
570
|
+
cfg: next,
|
|
571
|
+
accountId,
|
|
572
|
+
prompter: params.prompter,
|
|
573
|
+
runtime: params.runtime
|
|
574
|
+
});
|
|
575
|
+
else if (mode === "manual") next = await linkViaManualInput({
|
|
576
|
+
cfg: next,
|
|
577
|
+
accountId,
|
|
578
|
+
prompter: params.prompter
|
|
579
|
+
});
|
|
580
|
+
else if (!configured) await params.prompter.note(["您可以稍后运行以下命令重新选择 QQ Bot 进行配置:", " openclaw channels add"].join("\n"), "QQ Bot");
|
|
581
|
+
return { cfg: next };
|
|
582
|
+
}
|
|
583
|
+
//#endregion
|
|
584
|
+
//#region extensions/qqbot/src/bridge/setup/surface.ts
|
|
585
|
+
const channel = "qqbot";
|
|
586
|
+
const qqbotSetupWizard = {
|
|
587
|
+
channel,
|
|
588
|
+
status: createStandardChannelSetupStatus({
|
|
589
|
+
channelLabel: "QQ Bot",
|
|
590
|
+
configuredLabel: "configured",
|
|
591
|
+
unconfiguredLabel: "needs AppID + AppSercet",
|
|
592
|
+
configuredHint: "configured",
|
|
593
|
+
unconfiguredHint: "needs AppID + AppSercet",
|
|
594
|
+
configuredScore: 1,
|
|
595
|
+
unconfiguredScore: 6,
|
|
596
|
+
resolveConfigured: ({ cfg, accountId }) => (accountId ? [accountId] : listQQBotAccountIds(cfg)).some((resolvedAccountId) => {
|
|
597
|
+
return isAccountConfigured(resolveQQBotAccount(cfg, resolvedAccountId, { allowUnresolvedSecretRef: true }));
|
|
598
|
+
})
|
|
599
|
+
}),
|
|
600
|
+
credentials: [],
|
|
601
|
+
finalize: async ({ cfg, accountId, forceAllowFrom, prompter, runtime }) => await finalizeQQBotSetup({
|
|
602
|
+
cfg,
|
|
603
|
+
accountId,
|
|
604
|
+
forceAllowFrom,
|
|
605
|
+
prompter,
|
|
606
|
+
runtime
|
|
607
|
+
}),
|
|
608
|
+
disable: (cfg) => setSetupChannelEnabled(cfg, channel, false)
|
|
609
|
+
};
|
|
610
|
+
//#endregion
|
|
611
|
+
//#region extensions/qqbot/src/config-schema.ts
|
|
612
|
+
const AudioFormatPolicySchema = z.object({
|
|
613
|
+
sttDirectFormats: z.array(z.string()).optional(),
|
|
614
|
+
uploadDirectFormats: z.array(z.string()).optional(),
|
|
615
|
+
transcodeEnabled: z.boolean().optional()
|
|
616
|
+
}).optional();
|
|
617
|
+
const QQBotSttSchema = z.object({
|
|
618
|
+
enabled: z.boolean().optional(),
|
|
619
|
+
provider: z.string().optional(),
|
|
620
|
+
baseUrl: z.string().optional(),
|
|
621
|
+
apiKey: z.string().optional(),
|
|
622
|
+
model: z.string().optional()
|
|
623
|
+
}).strict().optional();
|
|
624
|
+
/** When `true`, same as `mode: "partial"` and `c2cStreamApi: true` for C2C. Object form kept for legacy configs. */
|
|
625
|
+
const QQBotStreamingSchema = z.union([z.boolean(), z.object({
|
|
626
|
+
/** "partial" (default) enables block streaming; "off" disables it. */
|
|
627
|
+
mode: z.enum(["off", "partial"]).default("partial"),
|
|
628
|
+
/** @deprecated Prefer `streaming: true`. */
|
|
629
|
+
c2cStreamApi: z.boolean().optional()
|
|
630
|
+
}).passthrough()]).optional();
|
|
631
|
+
const QQBotExecApprovalsSchema = z.object({
|
|
632
|
+
enabled: z.union([z.boolean(), z.literal("auto")]).optional(),
|
|
633
|
+
approvers: z.array(z.string()).optional(),
|
|
634
|
+
agentFilter: z.array(z.string()).optional(),
|
|
635
|
+
sessionFilter: z.array(z.string()).optional(),
|
|
636
|
+
target: z.enum([
|
|
637
|
+
"dm",
|
|
638
|
+
"channel",
|
|
639
|
+
"both"
|
|
640
|
+
]).optional()
|
|
641
|
+
}).strict().optional();
|
|
642
|
+
const QQBotDmPolicySchema = z.enum([
|
|
643
|
+
"open",
|
|
644
|
+
"allowlist",
|
|
645
|
+
"disabled"
|
|
646
|
+
]).optional();
|
|
647
|
+
const QQBotGroupPolicySchema = z.enum([
|
|
648
|
+
"open",
|
|
649
|
+
"allowlist",
|
|
650
|
+
"disabled"
|
|
651
|
+
]).optional();
|
|
652
|
+
const QQBotAccountSchema = z.object({
|
|
653
|
+
enabled: z.boolean().optional(),
|
|
654
|
+
name: z.string().optional(),
|
|
655
|
+
appId: z.string().optional(),
|
|
656
|
+
clientSecret: buildSecretInputSchema().optional(),
|
|
657
|
+
clientSecretFile: z.string().optional(),
|
|
658
|
+
allowFrom: AllowFromListSchema,
|
|
659
|
+
groupAllowFrom: AllowFromListSchema,
|
|
660
|
+
dmPolicy: QQBotDmPolicySchema,
|
|
661
|
+
groupPolicy: QQBotGroupPolicySchema,
|
|
662
|
+
systemPrompt: z.string().optional(),
|
|
663
|
+
markdownSupport: z.boolean().optional(),
|
|
664
|
+
voiceDirectUploadFormats: z.array(z.string()).optional(),
|
|
665
|
+
audioFormatPolicy: AudioFormatPolicySchema,
|
|
666
|
+
urlDirectUpload: z.boolean().optional(),
|
|
667
|
+
upgradeUrl: z.string().optional(),
|
|
668
|
+
upgradeMode: z.enum(["doc", "hot-reload"]).optional(),
|
|
669
|
+
streaming: QQBotStreamingSchema,
|
|
670
|
+
execApprovals: QQBotExecApprovalsSchema
|
|
671
|
+
}).passthrough();
|
|
672
|
+
const qqbotChannelConfigSchema = buildChannelConfigSchema(QQBotAccountSchema.extend({
|
|
673
|
+
stt: QQBotSttSchema,
|
|
674
|
+
accounts: z.object({}).catchall(QQBotAccountSchema.passthrough()).optional(),
|
|
675
|
+
defaultAccount: z.string().optional()
|
|
676
|
+
}).passthrough());
|
|
677
|
+
//#endregion
|
|
678
|
+
export { qqbotSetupAdapterShared as a, listQQBotAccountIds as c, DEFAULT_ACCOUNT_ID$2 as d, resolveAccountBase as f, setBridgeLogger as h, qqbotMeta as i, resolveDefaultQQBotAccountId as l, getBridgeLogger as m, qqbotSetupWizard as n, DEFAULT_ACCOUNT_ID$1 as o, ensurePlatformAdapter as p, qqbotConfigAdapter as r, applyQQBotAccountConfig as s, qqbotChannelConfigSchema as t, resolveQQBotAccount as u };
|
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
import { E as setOutboundAudioPort, _ as sendVoice, c as isMediaPayload, g as sendVideoMsg, h as sendPhoto, l as parseQQBotPayload, m as sendDocument, o as encodePayloadForCron, r as sendMedia, s as isCronReminderPayload, u as normalizeMediaTags, v as resolveUserFacingMediaError, w as DEFAULT_MEDIA_SEND_ERROR } from "./outbound-
|
|
1
|
+
import { E as setOutboundAudioPort, _ as sendVoice, c as isMediaPayload, g as sendVideoMsg, h as sendPhoto, l as parseQQBotPayload, m as sendDocument, o as encodePayloadForCron, r as sendMedia, s as isCronReminderPayload, u as normalizeMediaTags, v as resolveUserFacingMediaError, w as DEFAULT_MEDIA_SEND_ERROR } from "./outbound-DTQUASKu.js";
|
|
2
2
|
import { c as getPlatformAdapter, i as normalizeOptionalString, n as normalizeLowercaseStringOrEmpty, o as readStringField, s as sanitizeFileName, t as asOptionalObjectRecord } from "./string-normalize-C46CS-F1.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { t as
|
|
6
|
-
import {
|
|
7
|
-
import { n as getQQBotRuntimeForEngine, t as getQQBotRuntime } from "./runtime-B-cqLImu.js";
|
|
8
|
-
import { a as getHomeDir, c as getQQBotMediaDir, d as isLocalPath, f as isWindows, i as checkSilkWasmAvailable, m as resolveQQBotPayloadLocalFilePath, o as getQQBotDataDir, p as normalizePath$1, s as getQQBotDataPath, u as getTempDir } from "./target-parser-ByU3srDK.js";
|
|
9
|
-
import { a as getPluginVersion, i as getFrameworkVersion, n as runWithRequestContext, o as initCommands, s as matchSlashCommand } from "./request-context-Betw4nJr.js";
|
|
3
|
+
import { f as resolveAccountBase, h as setBridgeLogger, p as ensurePlatformAdapter } from "./config-schema-BE5YP0NG.js";
|
|
4
|
+
import { C as parseApprovalButtonData, a as getQQBotDataDir, d as isWindows, f as normalizePath$1, h as authorizeQQBotApprovalAction, i as getHomeDir, l as getTempDir, m as toGatewayAccount, o as getQQBotDataPath, p as resolveQQBotPayloadLocalFilePath, r as checkSilkWasmAvailable, s as getQQBotMediaDir, u as isLocalPath } from "./channel-nG7HntSR.js";
|
|
5
|
+
import { B as StreamContentType, C as debugError, D as getNextMsgSeq, F as getImageMimeType, H as StreamInputState, I as getMaxUploadSize, N as formatFileSize, R as formatDuration, S as withTokenRetry, T as debugWarn, V as StreamInputMode, _ as sendInputNotify, a as acknowledgeInteraction, b as startBackgroundTokenRefresh, c as createRawInputNotifyFn, d as getMessageApi, f as getPluginUserAgent, g as registerAccount, h as onMessageSent, i as accountToCreds, j as downloadFile, k as openLocalFile, l as getAccessToken, m as initSender, n as getQQBotRuntimeForEngine, o as buildDeliveryTarget, p as initApiConfig, s as clearTokenCache, t as getQQBotRuntime, u as getGatewayUrl, v as sendMedia$1, w as debugLog, x as stopBackgroundTokenRefresh, y as sendText, z as formatErrorMessage } from "./runtime-BFcYWYuk.js";
|
|
6
|
+
import { a as getPluginVersion, i as getFrameworkVersion, n as runWithRequestContext, o as initCommands, s as matchSlashCommand } from "./request-context-DiWgzdpn.js";
|
|
10
7
|
import * as fs$1 from "node:fs";
|
|
11
8
|
import fs from "node:fs";
|
|
12
9
|
import * as os$1 from "node:os";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { m as getBridgeLogger, p as ensurePlatformAdapter, u as resolveQQBotAccount } from "./config-schema-BE5YP0NG.js";
|
|
2
|
+
import { S as buildPluginApprovalText, _ as matchesQQBotApprovalAccount, b as buildApprovalKeyboard, g as isQQBotExecApprovalClientEnabled, v as resolveQQBotExecApprovalConfig, w as resolveApprovalTarget, x as buildExecApprovalText, y as shouldHandleQQBotExecApprovalRequest } from "./channel-nG7HntSR.js";
|
|
3
|
+
import { d as getMessageApi, i as accountToCreds } from "./runtime-BFcYWYuk.js";
|
|
4
4
|
import { resolveApprovalRequestSessionConversation } from "openclaw/plugin-sdk/approval-native-runtime";
|
|
5
5
|
import { createChannelApprovalNativeRuntimeAdapter } from "openclaw/plugin-sdk/approval-handler-runtime";
|
|
6
6
|
//#region extensions/qqbot/src/bridge/approval/handler-runtime.ts
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { i as normalizeOptionalString, n as normalizeLowercaseStringOrEmpty, s as sanitizeFileName } from "./string-normalize-C46CS-F1.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { a as getQQBotDataDir, f as normalizePath, n as parseTarget$1, p as resolveQQBotPayloadLocalFilePath, s as getQQBotMediaDir, u as isLocalPath } from "./channel-nG7HntSR.js";
|
|
3
|
+
import { A as checkFileSize, C as debugError, E as UploadDailyLimitExceededError, F as getImageMimeType, I as getMaxUploadSize, L as readFileAsync, M as fileExistsAsync, N as formatFileSize, O as UPLOAD_PREPARE_FALLBACK_CODE, P as getFileTypeName, T as debugWarn, i as accountToCreds, j as downloadFile, p as initApiConfig, v as sendMedia$1, w as debugLog, y as sendText$1, z as formatErrorMessage } from "./runtime-BFcYWYuk.js";
|
|
4
4
|
import { pathExistsSync, resolveLocalPathFromRootsSync } from "openclaw/plugin-sdk/security-runtime";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import { getFileExtension } from "openclaw/plugin-sdk/media-mime";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { a as getQQBotDataDir, c as getQQBotMediaPath, d as isWindows, i as getHomeDir } from "./channel-nG7HntSR.js";
|
|
2
|
+
import { w as debugLog } from "./runtime-BFcYWYuk.js";
|
|
3
3
|
import fs from "node:fs";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { loadJsonFile } from "openclaw/plugin-sdk/json-store";
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { c as getPlatformAdapter, i as normalizeOptionalString, s as sanitizeFileName } from "./string-normalize-C46CS-F1.js";
|
|
2
2
|
import * as fs$1 from "node:fs";
|
|
3
|
+
import { createPluginRuntimeStore } from "openclaw/plugin-sdk/runtime-store";
|
|
3
4
|
import os from "node:os";
|
|
4
5
|
import * as crypto$1 from "node:crypto";
|
|
5
6
|
import crypto from "node:crypto";
|
|
@@ -1962,4 +1963,19 @@ function supportsRichMedia(targetType) {
|
|
|
1962
1963
|
return targetType === "c2c" || targetType === "group";
|
|
1963
1964
|
}
|
|
1964
1965
|
//#endregion
|
|
1965
|
-
|
|
1966
|
+
//#region extensions/qqbot/src/bridge/runtime.ts
|
|
1967
|
+
const { setRuntime: _setRuntime, getRuntime: getQQBotRuntime } = createPluginRuntimeStore({
|
|
1968
|
+
pluginId: "qqbot",
|
|
1969
|
+
errorMessage: "QQBot runtime not initialized"
|
|
1970
|
+
});
|
|
1971
|
+
/** Set the QQBot runtime and inject the framework version into the User-Agent. */
|
|
1972
|
+
function setQQBotRuntime(runtime) {
|
|
1973
|
+
_setRuntime(runtime);
|
|
1974
|
+
setOpenClawVersion(runtime.version);
|
|
1975
|
+
}
|
|
1976
|
+
/** Type-narrowed getter for engine/ modules that need GatewayPluginRuntime. */
|
|
1977
|
+
function getQQBotRuntimeForEngine() {
|
|
1978
|
+
return getQQBotRuntime();
|
|
1979
|
+
}
|
|
1980
|
+
//#endregion
|
|
1981
|
+
export { checkFileSize as A, StreamContentType as B, debugError as C, getNextMsgSeq as D, UploadDailyLimitExceededError as E, getImageMimeType as F, StreamInputState as H, getMaxUploadSize as I, readFileAsync as L, fileExistsAsync as M, formatFileSize as N, UPLOAD_PREPARE_FALLBACK_CODE as O, getFileTypeName as P, formatDuration as R, withTokenRetry as S, debugWarn as T, StreamInputMode as V, sendInputNotify as _, acknowledgeInteraction as a, startBackgroundTokenRefresh as b, createRawInputNotifyFn as c, getMessageApi as d, getPluginUserAgent as f, registerAccount as g, onMessageSent as h, accountToCreds as i, downloadFile as j, openLocalFile as k, getAccessToken as l, initSender as m, getQQBotRuntimeForEngine as n, buildDeliveryTarget as o, initApiConfig as p, setQQBotRuntime as r, clearTokenCache as s, getQQBotRuntime as t, getGatewayUrl as u, sendMedia as v, debugLog as w, stopBackgroundTokenRefresh as x, sendText as y, formatErrorMessage as z };
|
package/dist/runtime-api.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { r as setQQBotRuntime, t as getQQBotRuntime } from "./runtime-
|
|
1
|
+
import { r as setQQBotRuntime, t as getQQBotRuntime } from "./runtime-BFcYWYuk.js";
|
|
2
2
|
export { getQQBotRuntime, setQQBotRuntime };
|
package/dist/setup-plugin-api.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as qqbotSetupPlugin } from "./channel.setup-
|
|
1
|
+
import { t as qqbotSetupPlugin } from "./channel.setup-D_8Ryfln.js";
|
|
2
2
|
export { qqbotSetupPlugin };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/qqbot",
|
|
3
|
-
"version": "2026.5.14-beta.
|
|
3
|
+
"version": "2026.5.14-beta.2",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "OpenClaw QQ Bot channel plugin",
|
|
6
6
|
"repository": {
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"@tencent-connect/qqbot-connector": "1.1.0",
|
|
13
13
|
"mpg123-decoder": "1.0.3",
|
|
14
14
|
"silk-wasm": "3.7.1",
|
|
15
|
-
"ws": "8.20.
|
|
15
|
+
"ws": "8.20.1",
|
|
16
16
|
"zod": "4.4.3"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"openclaw": "workspace:*"
|
|
22
22
|
},
|
|
23
23
|
"peerDependencies": {
|
|
24
|
-
"openclaw": ">=2026.5.14-beta.
|
|
24
|
+
"openclaw": ">=2026.5.14-beta.2"
|
|
25
25
|
},
|
|
26
26
|
"peerDependenciesMeta": {
|
|
27
27
|
"openclaw": {
|
|
@@ -50,10 +50,10 @@
|
|
|
50
50
|
"minHostVersion": ">=2026.4.10"
|
|
51
51
|
},
|
|
52
52
|
"compat": {
|
|
53
|
-
"pluginApi": ">=2026.5.14-beta.
|
|
53
|
+
"pluginApi": ">=2026.5.14-beta.2"
|
|
54
54
|
},
|
|
55
55
|
"build": {
|
|
56
|
-
"openclawVersion": "2026.5.14-beta.
|
|
56
|
+
"openclawVersion": "2026.5.14-beta.2"
|
|
57
57
|
},
|
|
58
58
|
"release": {
|
|
59
59
|
"publishToClawHub": true,
|