@openclaw/qqbot 2026.7.1 → 2026.7.2-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 +8 -7
- package/dist/{channel-D1UztsnG.js → channel-BbwpkiY3.js} +99 -54
- package/dist/{channel-entry-C5YdhX3Y.js → channel-entry-Cj1lWXpt.js} +4 -4
- package/dist/channel-entry-api.js +1 -1
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel.setup-2ItDYKhz.js → channel.setup-DfhritPL.js} +1 -1
- package/dist/{config-C1qZbh0K.js → config-CpOXnoEc.js} +2 -2
- package/dist/{config-schema-JZEf1dvB.js → config-schema-B5Mle_87.js} +38 -47
- package/dist/doctor-contract-api.js +1 -1
- package/dist/{gateway-pJQppxe4.js → gateway-be5-Ckdc.js} +284 -174
- package/dist/{group-o0GmovSf.js → group-Dbpnjalm.js} +19 -17
- package/dist/{handler-runtime-zQvT6SrI.js → handler-runtime-BvR-ayNW.js} +8 -12
- package/dist/{log-DEtcoDWe.js → log-Da4jz75I.js} +4 -8
- package/dist/{outbound-BIrfvvFJ.js → outbound-BLl8Tsu7.js} +8 -142
- package/dist/{runtime-DodcT_fQ.js → runtime-Du28LbOJ.js} +2 -2
- package/dist/runtime-api.js +1 -1
- package/dist/secret-contract-api.js +6 -22
- package/dist/{sender-CjDuU-uz.js → sender-0vqsivoI.js} +220 -66
- package/dist/setup-plugin-api.js +1 -1
- package/dist/state-keys-jLJ2SmJA.js +225 -0
- package/dist/{tools-UJJ-tLHP.js → tools-DYb23LBU.js} +48 -6
- package/dist/tools-api.js +1 -1
- package/node_modules/p-map/index.d.ts +155 -0
- package/node_modules/p-map/index.js +284 -0
- package/node_modules/p-map/license +9 -0
- package/node_modules/p-map/package.json +57 -0
- package/node_modules/p-map/readme.md +190 -0
- package/node_modules/parse-ms/index.d.ts +30 -0
- package/node_modules/parse-ms/index.js +45 -0
- package/node_modules/parse-ms/license +9 -0
- package/node_modules/parse-ms/package.json +47 -0
- package/node_modules/parse-ms/readme.md +46 -0
- package/node_modules/pretty-ms/index.d.ts +157 -0
- package/node_modules/pretty-ms/index.js +149 -0
- package/node_modules/pretty-ms/license +9 -0
- package/node_modules/pretty-ms/package.json +55 -0
- package/node_modules/pretty-ms/readme.md +179 -0
- package/npm-shrinkwrap.json +44 -3
- package/openclaw.plugin.json +61 -89
- package/package.json +8 -4
- package/dist/state-keys-CQKlAFyo.js +0 -141
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { t as asOptionalObjectRecord } from "./string-normalize-R_0cKO7Q.js";
|
|
2
|
-
import { d as resolveAccountBase } from "./config-
|
|
3
|
-
import { n as debugLog } from "./log-
|
|
4
|
-
import {
|
|
2
|
+
import { d as resolveAccountBase } from "./config-CpOXnoEc.js";
|
|
3
|
+
import { n as debugLog } from "./log-Da4jz75I.js";
|
|
4
|
+
import { O as getHomeDir, P as isWindows, j as getQQBotMediaPath, k as getQQBotDataDir } from "./outbound-BLl8Tsu7.js";
|
|
5
5
|
import { asBoolean, uniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
6
6
|
import fs from "node:fs";
|
|
7
7
|
import path from "node:path";
|
|
@@ -766,15 +766,10 @@ function registerLogCommands(registry) {
|
|
|
766
766
|
//#endregion
|
|
767
767
|
//#region extensions/qqbot/src/engine/commands/builtin/register-streaming.ts
|
|
768
768
|
function isStreamingConfigEnabled(streaming) {
|
|
769
|
-
if (streaming
|
|
770
|
-
|
|
771
|
-
if (
|
|
772
|
-
|
|
773
|
-
if (o.c2cStreamApi === true) return true;
|
|
774
|
-
if (o.mode === "off") return false;
|
|
775
|
-
return true;
|
|
776
|
-
}
|
|
777
|
-
return false;
|
|
769
|
+
if (!streaming || typeof streaming !== "object") return false;
|
|
770
|
+
const o = streaming;
|
|
771
|
+
if (o.nativeTransport === true) return true;
|
|
772
|
+
return o.mode !== "off";
|
|
778
773
|
}
|
|
779
774
|
function registerStreamingCommands(registry) {
|
|
780
775
|
registry.register({
|
|
@@ -820,7 +815,7 @@ function registerStreamingCommands(registry) {
|
|
|
820
815
|
``,
|
|
821
816
|
`\`\`\`shell`,
|
|
822
817
|
`# 1. 开启流式消息`,
|
|
823
|
-
`openclaw config set channels.qqbot.streaming true`,
|
|
818
|
+
`openclaw config set channels.qqbot.streaming.nativeTransport true`,
|
|
824
819
|
``,
|
|
825
820
|
`# 2. 重启网关使配置生效`,
|
|
826
821
|
`openclaw gateway restart`,
|
|
@@ -833,7 +828,10 @@ function registerStreamingCommands(registry) {
|
|
|
833
828
|
const qqbot = (currentCfg.channels ?? {}).qqbot;
|
|
834
829
|
if (!qqbot) return `❌ 配置文件中未找到 qqbot 通道配置`;
|
|
835
830
|
const accountId = ctx.accountId;
|
|
836
|
-
const newVal = wantOn
|
|
831
|
+
const newVal = wantOn ? {
|
|
832
|
+
mode: "partial",
|
|
833
|
+
nativeTransport: true
|
|
834
|
+
} : { mode: "off" };
|
|
837
835
|
if (accountId !== "default") {
|
|
838
836
|
const nextAccounts = { ...qqbot.accounts ?? {} };
|
|
839
837
|
const acct = { ...nextAccounts[accountId] };
|
|
@@ -912,7 +910,7 @@ const PRIVATE_ONLY_CORE_COMMANDS = /* @__PURE__ */ new Set([
|
|
|
912
910
|
"tools",
|
|
913
911
|
"skill",
|
|
914
912
|
"diagnostics",
|
|
915
|
-
"
|
|
913
|
+
"openclaw",
|
|
916
914
|
"tasks",
|
|
917
915
|
"allowlist",
|
|
918
916
|
"approve",
|
|
@@ -1097,13 +1095,17 @@ function getPluginVersion() {
|
|
|
1097
1095
|
function getFrameworkVersion() {
|
|
1098
1096
|
return getFrameworkVersionString();
|
|
1099
1097
|
}
|
|
1098
|
+
//#endregion
|
|
1099
|
+
//#region extensions/qqbot/src/engine/config/group.ts
|
|
1100
|
+
const DEFAULT_GROUP_HISTORY_LIMIT = 50;
|
|
1101
|
+
const DEFAULT_GROUP_COMMAND_LEVEL = "all";
|
|
1100
1102
|
const DEFAULT_GROUP_PROMPT = "If the sender is a bot, respond only when they explicitly @mention you to ask a question or request assistance with a specific task; keep your replies concise and clear, avoiding the urge to race other bots to answer or engage in lengthy, unproductive exchanges. In group chats, prioritize responding to messages from human users; bots should maintain a collaborative rather than competitive dynamic to ensure the conversation remains orderly and does not result in message flooding.";
|
|
1101
1103
|
const DEFAULT_GROUP_CONFIG = {
|
|
1102
1104
|
requireMention: true,
|
|
1103
1105
|
ignoreOtherMentions: false,
|
|
1104
|
-
commandLevel:
|
|
1106
|
+
commandLevel: DEFAULT_GROUP_COMMAND_LEVEL,
|
|
1105
1107
|
name: "",
|
|
1106
|
-
historyLimit:
|
|
1108
|
+
historyLimit: DEFAULT_GROUP_HISTORY_LIMIT
|
|
1107
1109
|
};
|
|
1108
1110
|
function readGroupsMap(cfg, accountId) {
|
|
1109
1111
|
const groups = asOptionalObjectRecord(resolveAccountBase(cfg, accountId).config.groups);
|
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
import { c as getMessageApi, t as accountToCreds } from "./sender-
|
|
2
|
-
import { o as ensurePlatformAdapter, s as getBridgeLogger } from "./config-schema-
|
|
3
|
-
import { c as resolveQQBotExecApprovalConfig, d as buildExecApprovalText, f as buildPluginApprovalText, l as shouldHandleQQBotExecApprovalRequest, m as resolveApprovalTarget, o as isQQBotExecApprovalClientEnabled, s as matchesQQBotApprovalAccount, u as buildApprovalKeyboard } from "./channel-
|
|
4
|
-
import { a as resolveQQBotAccount } from "./config-
|
|
1
|
+
import { c as getMessageApi, t as accountToCreds } from "./sender-0vqsivoI.js";
|
|
2
|
+
import { o as ensurePlatformAdapter, s as getBridgeLogger } from "./config-schema-B5Mle_87.js";
|
|
3
|
+
import { c as resolveQQBotExecApprovalConfig, d as buildExecApprovalText, f as buildPluginApprovalText, l as shouldHandleQQBotExecApprovalRequest, m as resolveApprovalTarget, o as isQQBotExecApprovalClientEnabled, s as matchesQQBotApprovalAccount, u as buildApprovalKeyboard } from "./channel-BbwpkiY3.js";
|
|
4
|
+
import { a as resolveQQBotAccount } from "./config-CpOXnoEc.js";
|
|
5
5
|
import { resolveApprovalRequestSessionConversation } from "openclaw/plugin-sdk/approval-native-runtime";
|
|
6
6
|
import { createChannelApprovalNativeRuntimeAdapter } from "openclaw/plugin-sdk/approval-handler-runtime";
|
|
7
7
|
//#region extensions/qqbot/src/bridge/approval/handler-runtime.ts
|
|
8
|
-
function isExecRequest(request) {
|
|
9
|
-
return "expiresAtMs" in request;
|
|
10
|
-
}
|
|
11
8
|
function resolveQQTarget(request) {
|
|
12
9
|
const sessionConversation = resolveApprovalRequestSessionConversation({
|
|
13
10
|
request,
|
|
@@ -70,11 +67,10 @@ const qqbotApprovalNativeRuntime = createChannelApprovalNativeRuntimeAdapter({
|
|
|
70
67
|
}
|
|
71
68
|
},
|
|
72
69
|
presentation: {
|
|
73
|
-
buildPendingPayload: ({
|
|
74
|
-
const
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
getBridgeLogger().debug?.(`[qqbot:approval-runtime] buildPendingPayload requestId=${req.id} kind=${isExecRequest(req) ? "exec" : "plugin"}`);
|
|
70
|
+
buildPendingPayload: ({ view, nowMs }) => {
|
|
71
|
+
const text = view.approvalKind === "exec" ? buildExecApprovalText(view, nowMs) : buildPluginApprovalText(view, nowMs);
|
|
72
|
+
const keyboard = buildApprovalKeyboard(view.approvalId, view.approvalKind, view.actions.map((action) => action.decision));
|
|
73
|
+
getBridgeLogger().debug?.(`[qqbot:approval-runtime] buildPendingPayload requestId=${view.approvalId} kind=${view.approvalKind}`);
|
|
78
74
|
return {
|
|
79
75
|
text,
|
|
80
76
|
keyboard
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
2
|
+
import prettyMilliseconds from "pretty-ms";
|
|
2
3
|
//#region extensions/qqbot/src/engine/utils/format.ts
|
|
3
4
|
/**
|
|
4
5
|
* General formatting and string utilities.
|
|
5
6
|
* 通用格式化与字符串工具。
|
|
6
7
|
*
|
|
7
|
-
* Pure utility functions with
|
|
8
|
-
* Replaces `openclaw/plugin-sdk/error-runtime` and `text-runtime`
|
|
9
|
-
* helpers for use inside engine/.
|
|
8
|
+
* Pure utility functions, with duration presentation from the plugin-local dependency.
|
|
10
9
|
*
|
|
11
10
|
* NOTE: The framework `formatErrorMessage` also applies `redactSensitiveText()`
|
|
12
11
|
* for token masking. We intentionally omit that here — the framework's log
|
|
@@ -46,11 +45,8 @@ function formatErrorMessage(err) {
|
|
|
46
45
|
}
|
|
47
46
|
/** Format a millisecond duration into a human-readable string (e.g. "5m 30s"). */
|
|
48
47
|
function formatDuration(durationMs) {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
const minutes = Math.floor(seconds / 60);
|
|
52
|
-
const remainSeconds = seconds % 60;
|
|
53
|
-
return remainSeconds > 0 ? `${minutes}m ${remainSeconds}s` : `${minutes}m`;
|
|
48
|
+
if (durationMs <= 0) return "0s";
|
|
49
|
+
return prettyMilliseconds(durationMs < 1e3 ? Math.round(durationMs) : Math.round(durationMs / 1e3) * 1e3, { unitCount: 2 });
|
|
54
50
|
}
|
|
55
51
|
//#endregion
|
|
56
52
|
//#region extensions/qqbot/src/engine/utils/log.ts
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { A as
|
|
1
|
+
import { A as UPLOAD_PREPARE_FALLBACK_CODE, C as checkMessageReplyLimit, D as recordMessageReply, E as getMessageReplyStats, F as formatFileSize, I as getFileTypeName, L as getImageMimeType, M as checkFileSize, N as downloadFile, O as UploadDailyLimitExceededError, P as fileExistsAsync, R as getMaxUploadSize, T as getMessageReplyConfig, U as __exportAll, g as sendText$1, h as sendMedia$1, t as accountToCreds, u as initApiConfig, z as readFileAsync } from "./sender-0vqsivoI.js";
|
|
2
2
|
import { c as getPlatformAdapter, i as normalizeOptionalString, n as normalizeLowercaseStringOrEmpty, s as sanitizeFileName } from "./string-normalize-R_0cKO7Q.js";
|
|
3
|
-
import { a as formatErrorMessage, n as debugLog, r as debugWarn, t as debugError } from "./log-
|
|
3
|
+
import { a as formatErrorMessage, n as debugLog, r as debugWarn, t as debugError } from "./log-Da4jz75I.js";
|
|
4
4
|
import { r as parseTarget$1 } from "./target-parser-DagYRQkP.js";
|
|
5
5
|
import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
6
6
|
import * as fs$2 from "node:fs";
|
|
@@ -262,122 +262,6 @@ const OUTBOUND_ERROR_CODES = {
|
|
|
262
262
|
};
|
|
263
263
|
const DEFAULT_MEDIA_SEND_ERROR = "发送失败,请稍后重试。";
|
|
264
264
|
//#endregion
|
|
265
|
-
//#region extensions/qqbot/src/engine/messaging/reply-limiter.ts
|
|
266
|
-
const DEFAULT_LIMIT = 4;
|
|
267
|
-
const DEFAULT_TTL_MS = 3600 * 1e3;
|
|
268
|
-
const DEFAULT_MAX_TRACKED = 1e4;
|
|
269
|
-
/**
|
|
270
|
-
* Per-account reply limiter with automatic eviction.
|
|
271
|
-
*
|
|
272
|
-
* Usage:
|
|
273
|
-
* ```ts
|
|
274
|
-
* const limiter = new ReplyLimiter({ limit: 4, ttlMs: 3600000 });
|
|
275
|
-
* const check = limiter.checkLimit(messageId);
|
|
276
|
-
* if (check.allowed) {
|
|
277
|
-
* await sendPassiveReply(...);
|
|
278
|
-
* limiter.record(messageId);
|
|
279
|
-
* } else if (check.shouldFallbackToProactive) {
|
|
280
|
-
* await sendProactiveMessage(...);
|
|
281
|
-
* }
|
|
282
|
-
* ```
|
|
283
|
-
*/
|
|
284
|
-
var ReplyLimiter = class {
|
|
285
|
-
constructor(config) {
|
|
286
|
-
this.tracker = /* @__PURE__ */ new Map();
|
|
287
|
-
this.limit = config?.limit ?? DEFAULT_LIMIT;
|
|
288
|
-
this.ttlMs = config?.ttlMs ?? DEFAULT_TTL_MS;
|
|
289
|
-
this.maxTracked = config?.maxTrackedMessages ?? DEFAULT_MAX_TRACKED;
|
|
290
|
-
}
|
|
291
|
-
/** Check whether a passive reply is allowed for the given message. */
|
|
292
|
-
checkLimit(messageId) {
|
|
293
|
-
const now = Date.now();
|
|
294
|
-
this.evictIfNeeded(now);
|
|
295
|
-
const record = this.tracker.get(messageId);
|
|
296
|
-
if (!record) return {
|
|
297
|
-
allowed: true,
|
|
298
|
-
remaining: this.limit,
|
|
299
|
-
shouldFallbackToProactive: false
|
|
300
|
-
};
|
|
301
|
-
if (now - record.firstReplyAt > this.ttlMs) return {
|
|
302
|
-
allowed: false,
|
|
303
|
-
remaining: 0,
|
|
304
|
-
shouldFallbackToProactive: true,
|
|
305
|
-
fallbackReason: "expired",
|
|
306
|
-
message: `Message is older than ${this.ttlMs / (3600 * 1e3)}h; sending as a proactive message instead`
|
|
307
|
-
};
|
|
308
|
-
const remaining = this.limit - record.count;
|
|
309
|
-
if (remaining <= 0) return {
|
|
310
|
-
allowed: false,
|
|
311
|
-
remaining: 0,
|
|
312
|
-
shouldFallbackToProactive: true,
|
|
313
|
-
fallbackReason: "limit_exceeded",
|
|
314
|
-
message: `Passive reply limit reached (${this.limit} per hour); sending proactively instead`
|
|
315
|
-
};
|
|
316
|
-
return {
|
|
317
|
-
allowed: true,
|
|
318
|
-
remaining,
|
|
319
|
-
shouldFallbackToProactive: false
|
|
320
|
-
};
|
|
321
|
-
}
|
|
322
|
-
/** Record one passive reply against a message. */
|
|
323
|
-
record(messageId) {
|
|
324
|
-
const now = Date.now();
|
|
325
|
-
const existing = this.tracker.get(messageId);
|
|
326
|
-
if (!existing) this.tracker.set(messageId, {
|
|
327
|
-
count: 1,
|
|
328
|
-
firstReplyAt: now
|
|
329
|
-
});
|
|
330
|
-
else if (now - existing.firstReplyAt > this.ttlMs) this.tracker.set(messageId, {
|
|
331
|
-
count: 1,
|
|
332
|
-
firstReplyAt: now
|
|
333
|
-
});
|
|
334
|
-
else existing.count++;
|
|
335
|
-
}
|
|
336
|
-
/** Return diagnostic stats. */
|
|
337
|
-
getStats() {
|
|
338
|
-
let totalReplies = 0;
|
|
339
|
-
for (const record of this.tracker.values()) totalReplies += record.count;
|
|
340
|
-
return {
|
|
341
|
-
trackedMessages: this.tracker.size,
|
|
342
|
-
totalReplies
|
|
343
|
-
};
|
|
344
|
-
}
|
|
345
|
-
/** Return limiter configuration. */
|
|
346
|
-
getConfig() {
|
|
347
|
-
return {
|
|
348
|
-
limit: this.limit,
|
|
349
|
-
ttlMs: this.ttlMs,
|
|
350
|
-
ttlHours: this.ttlMs / (3600 * 1e3)
|
|
351
|
-
};
|
|
352
|
-
}
|
|
353
|
-
/** Clear all tracked records. */
|
|
354
|
-
clear() {
|
|
355
|
-
this.tracker.clear();
|
|
356
|
-
}
|
|
357
|
-
/** Opportunistically evict expired records to keep the tracker bounded. */
|
|
358
|
-
evictIfNeeded(now) {
|
|
359
|
-
if (this.tracker.size <= this.maxTracked) return;
|
|
360
|
-
for (const [id, rec] of this.tracker) if (now - rec.firstReplyAt > this.ttlMs) this.tracker.delete(id);
|
|
361
|
-
}
|
|
362
|
-
};
|
|
363
|
-
//#endregion
|
|
364
|
-
//#region extensions/qqbot/src/engine/messaging/outbound-reply.ts
|
|
365
|
-
const replyLimiter = new ReplyLimiter();
|
|
366
|
-
const MESSAGE_REPLY_LIMIT = 4;
|
|
367
|
-
function checkMessageReplyLimit(messageId) {
|
|
368
|
-
return replyLimiter.checkLimit(messageId);
|
|
369
|
-
}
|
|
370
|
-
function recordMessageReply(messageId) {
|
|
371
|
-
replyLimiter.record(messageId);
|
|
372
|
-
debugLog(`[qqbot] recordMessageReply: ${messageId}, count=${replyLimiter.getStats().totalReplies}`);
|
|
373
|
-
}
|
|
374
|
-
function getMessageReplyStats() {
|
|
375
|
-
return replyLimiter.getStats();
|
|
376
|
-
}
|
|
377
|
-
function getMessageReplyConfig() {
|
|
378
|
-
return replyLimiter.getConfig();
|
|
379
|
-
}
|
|
380
|
-
//#endregion
|
|
381
265
|
//#region extensions/qqbot/src/engine/messaging/outbound-result-helpers.ts
|
|
382
266
|
/**
|
|
383
267
|
* Convert a media send result into a user-facing message.
|
|
@@ -1491,7 +1375,7 @@ function decodeMediaPath(raw, log) {
|
|
|
1491
1375
|
const code = decoded.charCodeAt(i);
|
|
1492
1376
|
if (code <= 255) bytes.push(code);
|
|
1493
1377
|
else {
|
|
1494
|
-
const charBytes = Buffer.from(decoded
|
|
1378
|
+
const charBytes = Buffer.from(decoded.charAt(i), "utf8");
|
|
1495
1379
|
bytes.push(...charBytes);
|
|
1496
1380
|
}
|
|
1497
1381
|
}
|
|
@@ -1545,7 +1429,7 @@ function isVideoFile$1(filePath, mimeType) {
|
|
|
1545
1429
|
//#region extensions/qqbot/src/engine/messaging/outbound.ts
|
|
1546
1430
|
var outbound_exports = /* @__PURE__ */ __exportAll({
|
|
1547
1431
|
DEFAULT_MEDIA_SEND_ERROR: () => DEFAULT_MEDIA_SEND_ERROR,
|
|
1548
|
-
MESSAGE_REPLY_LIMIT: () =>
|
|
1432
|
+
MESSAGE_REPLY_LIMIT: () => 5,
|
|
1549
1433
|
OUTBOUND_ERROR_CODES: () => OUTBOUND_ERROR_CODES,
|
|
1550
1434
|
buildMediaTarget: () => buildMediaTarget,
|
|
1551
1435
|
checkMessageReplyLimit: () => checkMessageReplyLimit,
|
|
@@ -1579,8 +1463,8 @@ const mediaPathDecodeLog = {
|
|
|
1579
1463
|
*/
|
|
1580
1464
|
async function sendText(ctx) {
|
|
1581
1465
|
const { to, account } = ctx;
|
|
1582
|
-
|
|
1583
|
-
let
|
|
1466
|
+
const { replyToId } = ctx;
|
|
1467
|
+
let { text } = ctx;
|
|
1584
1468
|
initApiConfig(account.appId, { markdownSupport: account.markdownSupport });
|
|
1585
1469
|
debugLog("[qqbot] sendText ctx:", JSON.stringify({
|
|
1586
1470
|
to,
|
|
@@ -1588,21 +1472,6 @@ async function sendText(ctx) {
|
|
|
1588
1472
|
replyToId,
|
|
1589
1473
|
accountId: account.accountId
|
|
1590
1474
|
}, null, 2));
|
|
1591
|
-
if (replyToId) {
|
|
1592
|
-
const limitCheck = checkMessageReplyLimit(replyToId);
|
|
1593
|
-
if (!limitCheck.allowed) if (limitCheck.shouldFallbackToProactive) {
|
|
1594
|
-
debugWarn(`[qqbot] sendText: passive reply unavailable, falling back to proactive send - ${limitCheck.message}`);
|
|
1595
|
-
fallbackToProactive = true;
|
|
1596
|
-
replyToId = null;
|
|
1597
|
-
} else {
|
|
1598
|
-
debugError(`[qqbot] sendText: passive reply was blocked without a fallback path - ${limitCheck.message}`);
|
|
1599
|
-
return {
|
|
1600
|
-
channel: "qqbot",
|
|
1601
|
-
error: limitCheck.message
|
|
1602
|
-
};
|
|
1603
|
-
}
|
|
1604
|
-
else debugLog(`[qqbot] sendText: remaining passive replies for ${replyToId}: ${limitCheck.remaining}/4`);
|
|
1605
|
-
}
|
|
1606
1475
|
text = normalizeMediaTags(text);
|
|
1607
1476
|
const mediaTagMatches = text.match(/<(qqimg|qqvoice|qqvideo|qqfile|qqmedia)>([^<>]+)<\/(?:qqimg|qqvoice|qqvideo|qqfile|qqmedia|img)>/gi);
|
|
1608
1477
|
if (mediaTagMatches && mediaTagMatches.length > 0) {
|
|
@@ -1675,7 +1544,6 @@ async function sendText(ctx) {
|
|
|
1675
1544
|
type: target.type === "channel" ? "channel" : target.type,
|
|
1676
1545
|
id: target.id
|
|
1677
1546
|
}, item.content, creds, { msgId: replyToId ?? void 0 });
|
|
1678
|
-
if (replyToId) recordMessageReply(replyToId);
|
|
1679
1547
|
lastResult = {
|
|
1680
1548
|
channel: "qqbot",
|
|
1681
1549
|
messageId: result.id,
|
|
@@ -1716,8 +1584,7 @@ async function sendText(ctx) {
|
|
|
1716
1584
|
error: "Proactive messages require non-empty content (--message cannot be empty)"
|
|
1717
1585
|
};
|
|
1718
1586
|
}
|
|
1719
|
-
|
|
1720
|
-
else debugLog(`[qqbot] sendText: sending proactive message to ${to}, length=${text.length}`);
|
|
1587
|
+
debugLog(`[qqbot] sendText: sending proactive message to ${to}, length=${text.length}`);
|
|
1721
1588
|
}
|
|
1722
1589
|
if (!account.appId || !account.clientSecret) return {
|
|
1723
1590
|
channel: "qqbot",
|
|
@@ -1732,7 +1599,6 @@ async function sendText(ctx) {
|
|
|
1732
1599
|
};
|
|
1733
1600
|
debugLog("[qqbot] sendText target:", JSON.stringify(target));
|
|
1734
1601
|
const result = await sendText$1(deliveryTarget, text, creds, { msgId: replyToId ?? void 0 });
|
|
1735
|
-
if (replyToId) recordMessageReply(replyToId);
|
|
1736
1602
|
return {
|
|
1737
1603
|
channel: "qqbot",
|
|
1738
1604
|
messageId: result.id,
|
|
@@ -1864,4 +1730,4 @@ async function sendCronMessage(account, to, message) {
|
|
|
1864
1730
|
});
|
|
1865
1731
|
}
|
|
1866
1732
|
//#endregion
|
|
1867
|
-
export {
|
|
1733
|
+
export { getQQBotMediaDir as A, resolveUserFacingMediaError as C, checkSilkWasmAvailable as D, setOutboundAudioPort as E, normalizePath$1 as F, getTempDir as M, isLocalPath as N, getHomeDir as O, isWindows as P, resolveWorkspaceScopedLocalRoots as S, OUTBOUND_ERROR_CODES as T, sendVideoMsg as _, sendText as a, resolveOutboundMediaLocalRoots as b, isCronReminderPayload as c, normalizeMediaTags as d, buildMediaTarget as f, sendPhoto as g, sendDocument as h, sendProactiveMessage as i, getQQBotMediaPath as j, getQQBotDataDir as k, isMediaPayload as l, resolveOutboundMediaPath as m, sendCronMessage as n, decodeMediaPath as o, parseTarget as p, sendMedia as r, encodePayloadForCron as s, outbound_exports as t, parseQQBotPayload as u, sendVoice as v, DEFAULT_MEDIA_SEND_ERROR as w, resolveWorkspacePathCandidates as x, resolveTrustedOutboundMediaPath as y };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { v as setOpenClawVersion } from "./sender-
|
|
1
|
+
import { v as setOpenClawVersion } from "./sender-0vqsivoI.js";
|
|
2
2
|
import { createPluginRuntimeStore } from "openclaw/plugin-sdk/runtime-store";
|
|
3
3
|
//#region extensions/qqbot/src/bridge/runtime.ts
|
|
4
|
-
const { setRuntime: _setRuntime,
|
|
4
|
+
const { setRuntime: _setRuntime, getRuntime: getQQBotRuntime } = createPluginRuntimeStore({
|
|
5
5
|
pluginId: "qqbot",
|
|
6
6
|
errorMessage: "QQBot runtime not initialized"
|
|
7
7
|
});
|
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-Du28LbOJ.js";
|
|
2
2
|
export { getQQBotRuntime, setQQBotRuntime };
|
|
@@ -1,27 +1,11 @@
|
|
|
1
|
-
import { collectConditionalChannelFieldAssignments, getChannelSurface, hasConfiguredSecretInputValue } from "openclaw/plugin-sdk/channel-secret-basic-runtime";
|
|
1
|
+
import { collectConditionalChannelFieldAssignments, createChannelSecretTargetRegistryEntries, getChannelSurface, hasConfiguredSecretInputValue } from "openclaw/plugin-sdk/channel-secret-basic-runtime";
|
|
2
2
|
//#region extensions/qqbot/src/secret-contract.ts
|
|
3
3
|
const DEFAULT_ACCOUNT_ID = "default";
|
|
4
|
-
const secretTargetRegistryEntries =
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
secretShape: "secret_input",
|
|
10
|
-
expectedResolvedValue: "string",
|
|
11
|
-
includeInPlan: true,
|
|
12
|
-
includeInConfigure: true,
|
|
13
|
-
includeInAudit: true
|
|
14
|
-
}, {
|
|
15
|
-
id: "channels.qqbot.clientSecret",
|
|
16
|
-
targetType: "channels.qqbot.clientSecret",
|
|
17
|
-
configFile: "openclaw.json",
|
|
18
|
-
pathPattern: "channels.qqbot.clientSecret",
|
|
19
|
-
secretShape: "secret_input",
|
|
20
|
-
expectedResolvedValue: "string",
|
|
21
|
-
includeInPlan: true,
|
|
22
|
-
includeInConfigure: true,
|
|
23
|
-
includeInAudit: true
|
|
24
|
-
}];
|
|
4
|
+
const secretTargetRegistryEntries = createChannelSecretTargetRegistryEntries({
|
|
5
|
+
channelKey: "qqbot",
|
|
6
|
+
account: ["clientSecret"],
|
|
7
|
+
channel: ["clientSecret"]
|
|
8
|
+
});
|
|
25
9
|
function hasTopLevelAppId(qqbot) {
|
|
26
10
|
if (typeof qqbot.appId === "string") return qqbot.appId.trim().length > 0;
|
|
27
11
|
return typeof qqbot.appId === "number";
|