@cxyhhhhh/openclaw-qqbot 2.0.0-dev.202607082305 → 2.0.0-dev.202607091556
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/index.cjs +133 -62
- package/dist/index.cjs.map +1 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/src/adapter/resolve.ts +4 -1
- package/src/config.ts +1 -1
- package/src/dispatch/body-assembler.ts +58 -21
- package/src/dispatch/ctx-builder.ts +110 -0
- package/src/dispatch/dispatch.ts +3 -42
- package/src/features/history-store.ts +7 -2
- package/src/gateway/middleware-setup.ts +20 -12
- package/skills/qqbot-group/SKILL.md +0 -75
- package/skills/qqbot-group/references/api_reference.md +0 -94
package/dist/index.cjs
CHANGED
|
@@ -4819,7 +4819,7 @@ function evaluateMatchedGroupAccessForPolicy(params) {
|
|
|
4819
4819
|
return { allowed: true, groupPolicy: params.groupPolicy, reason: "allowed" };
|
|
4820
4820
|
}
|
|
4821
4821
|
var DEFAULT_GROUP_POLICY = "open";
|
|
4822
|
-
var DEFAULT_GROUP_HISTORY_LIMIT =
|
|
4822
|
+
var DEFAULT_GROUP_HISTORY_LIMIT = 20;
|
|
4823
4823
|
var DEFAULT_GROUP_CONFIG = {
|
|
4824
4824
|
requireMention: true,
|
|
4825
4825
|
ignoreOtherMentions: false,
|
|
@@ -9093,7 +9093,7 @@ var import_node_path2 = __toESM(require("path"), 1);
|
|
|
9093
9093
|
var import_node_fs2 = __toESM(require("fs"), 1);
|
|
9094
9094
|
var _cachedOpenclawVersion;
|
|
9095
9095
|
function getPackageVersion() {
|
|
9096
|
-
return true ? "2.0.0-dev.
|
|
9096
|
+
return true ? "2.0.0-dev.202607091556" : "unknown";
|
|
9097
9097
|
}
|
|
9098
9098
|
function getOpenclawVersion(runtimeVersion) {
|
|
9099
9099
|
if (_cachedOpenclawVersion) return _cachedOpenclawVersion;
|
|
@@ -9541,11 +9541,15 @@ function resolveRuntimeAdapters(rt, log4) {
|
|
|
9541
9541
|
]);
|
|
9542
9542
|
const rawFinalizeContext = !rawBuildContext ? probeFunction(rt, [["channel", "reply", "finalizeInboundContext"]]) : null;
|
|
9543
9543
|
const buildInboundContext = rawBuildContext ? (params) => rawBuildContext(params) : rawFinalizeContext ? (params) => {
|
|
9544
|
+
const isCommand = params.access?.commands?.authorized ?? false;
|
|
9544
9545
|
const rawCtx = {
|
|
9545
9546
|
Body: params.message.body,
|
|
9546
9547
|
BodyForAgent: params.message.bodyForAgent,
|
|
9547
9548
|
RawBody: params.message.rawBody,
|
|
9548
9549
|
CommandBody: params.message.commandBody ?? params.message.rawBody,
|
|
9550
|
+
CommandSource: isCommand ? "text" : void 0,
|
|
9551
|
+
CommandTurn: params.command ?? void 0,
|
|
9552
|
+
CommandAuthorized: isCommand,
|
|
9549
9553
|
From: params.from,
|
|
9550
9554
|
To: params.reply.to,
|
|
9551
9555
|
SessionKey: params.route.routeSessionKey,
|
|
@@ -9560,7 +9564,6 @@ function resolveRuntimeAdapters(rt, log4) {
|
|
|
9560
9564
|
Timestamp: params.timestamp ?? Date.now(),
|
|
9561
9565
|
OriginatingChannel: params.channel,
|
|
9562
9566
|
OriginatingTo: params.reply.originatingTo ?? params.reply.to,
|
|
9563
|
-
CommandAuthorized: false,
|
|
9564
9567
|
...params.extra
|
|
9565
9568
|
};
|
|
9566
9569
|
return rawFinalizeContext(rawCtx);
|
|
@@ -11712,10 +11715,13 @@ async function downloadMediaFile(url, filename, log4) {
|
|
|
11712
11715
|
// src/dispatch/body-assembler.ts
|
|
11713
11716
|
var QUOTE_BEGIN = "[Quoted message begins]";
|
|
11714
11717
|
var QUOTE_END = "[Quoted message ends]";
|
|
11715
|
-
var
|
|
11716
|
-
var
|
|
11717
|
-
var
|
|
11718
|
-
var
|
|
11718
|
+
var REF_BEGIN = "[Reference message begins]";
|
|
11719
|
+
var REF_END = "[Reference message ends]";
|
|
11720
|
+
var HISTORY_BEGIN = "[Chat history begins]";
|
|
11721
|
+
var HISTORY_END = "[Chat history ends]";
|
|
11722
|
+
var MERGE_CTX_BEGIN = "[Merged messages begins]";
|
|
11723
|
+
var MERGE_CTX_END = "[Merged messages ends]";
|
|
11724
|
+
var CURRENT_MSG = "[Current message]";
|
|
11719
11725
|
function assembleBody(ctx, msg, account, getRuntime) {
|
|
11720
11726
|
const rawBody = msg.content ?? "";
|
|
11721
11727
|
const isGroup = msg.kind === "group";
|
|
@@ -11728,7 +11734,7 @@ function assembleBody(ctx, msg, account, getRuntime) {
|
|
|
11728
11734
|
const userContent = buildUserContent(ctx.message.content ?? "", processed);
|
|
11729
11735
|
const quotePart = buildQuotePart(quote);
|
|
11730
11736
|
const userMessage = mergedMessages && mergedMessages.length > 0 ? buildMergedUserMessage({ messages: mergedMessages, quotePart, isGroup, wasMentioned, getRuntime }) : buildUserMessage({ msg, userContent, quotePart, isGroup, wasMentioned });
|
|
11731
|
-
const dynamicCtx = buildDynamicCtx(processed);
|
|
11737
|
+
const dynamicCtx = buildDynamicCtx(processed, msg, quote);
|
|
11732
11738
|
const agentBody = buildAgentBody({
|
|
11733
11739
|
userContent,
|
|
11734
11740
|
base: dynamicCtx + userMessage,
|
|
@@ -11754,12 +11760,11 @@ ${voiceText}` : voiceText) + attachmentInfo;
|
|
|
11754
11760
|
}
|
|
11755
11761
|
function buildQuotePart(quote) {
|
|
11756
11762
|
if (!quote) return "";
|
|
11757
|
-
const sender = quote.entry?.senderName ? `${quote.entry.senderName} (${quote.entry.senderId})` : "";
|
|
11758
|
-
const senderLine = sender ? `${sender}: ` : "";
|
|
11759
11763
|
const text = quote.text || "Original content unavailable";
|
|
11760
11764
|
return `${QUOTE_BEGIN}
|
|
11761
|
-
${
|
|
11765
|
+
${text}
|
|
11762
11766
|
${QUOTE_END}
|
|
11767
|
+
${CURRENT_MSG}
|
|
11763
11768
|
`;
|
|
11764
11769
|
}
|
|
11765
11770
|
function buildUserMessage(input) {
|
|
@@ -11767,7 +11772,7 @@ function buildUserMessage(input) {
|
|
|
11767
11772
|
const atYouTag = isGroup && wasMentioned ? " (@you)" : "";
|
|
11768
11773
|
if (isGroup) {
|
|
11769
11774
|
const senderLabel = formatSenderLabel(msg.senderName, msg.senderId);
|
|
11770
|
-
return
|
|
11775
|
+
return `${quotePart}[${senderLabel}] ${userContent}${atYouTag}`;
|
|
11771
11776
|
}
|
|
11772
11777
|
return `${quotePart}${userContent}`;
|
|
11773
11778
|
}
|
|
@@ -11793,7 +11798,7 @@ function buildMergedUserMessage(input) {
|
|
|
11793
11798
|
return lines.join("\n");
|
|
11794
11799
|
}
|
|
11795
11800
|
const last = lines.pop();
|
|
11796
|
-
return [
|
|
11801
|
+
return [MERGE_CTX_BEGIN, ...lines, MERGE_CTX_END, CURRENT_MSG, last].join("\n");
|
|
11797
11802
|
}
|
|
11798
11803
|
function formatMergedLine(ctx, opts) {
|
|
11799
11804
|
const m3 = ctx.message;
|
|
@@ -11814,13 +11819,12 @@ function allSameSender(messages) {
|
|
|
11814
11819
|
const first = messages[0]?.message.senderId;
|
|
11815
11820
|
return messages.every((c) => c.message.senderId === first);
|
|
11816
11821
|
}
|
|
11817
|
-
function buildDynamicCtx(processed) {
|
|
11818
|
-
if (!processed) return "";
|
|
11822
|
+
function buildDynamicCtx(processed, msg, quote) {
|
|
11819
11823
|
const lines = [];
|
|
11820
|
-
if (processed
|
|
11824
|
+
if (processed?.imageUrls.length) {
|
|
11821
11825
|
lines.push(`- Images: ${processed.imageUrls.join(", ")}`);
|
|
11822
11826
|
}
|
|
11823
|
-
const transcripts = processed
|
|
11827
|
+
const transcripts = processed?.transcripts ?? [];
|
|
11824
11828
|
const voiceRefs = unique([
|
|
11825
11829
|
...transcripts.map((t) => t.localPath).filter(isNonEmpty),
|
|
11826
11830
|
...transcripts.map((t) => t.remoteUrl).filter(isNonEmpty)
|
|
@@ -11834,10 +11838,35 @@ function buildDynamicCtx(processed) {
|
|
|
11834
11838
|
if (asrTexts.length > 0) {
|
|
11835
11839
|
lines.push(`- ASR: ${asrTexts.join(" | ")}`);
|
|
11836
11840
|
}
|
|
11841
|
+
if (!quote) {
|
|
11842
|
+
const elementsCtx = buildMsgElementsContext(msg);
|
|
11843
|
+
if (elementsCtx.length > 0) {
|
|
11844
|
+
lines.push(REF_BEGIN, ...elementsCtx, REF_END);
|
|
11845
|
+
}
|
|
11846
|
+
}
|
|
11837
11847
|
return lines.length > 0 ? `${lines.join("\n")}
|
|
11838
11848
|
|
|
11839
11849
|
` : "";
|
|
11840
11850
|
}
|
|
11851
|
+
function buildMsgElementsContext(msg) {
|
|
11852
|
+
const elements = msg.msgElements;
|
|
11853
|
+
if (!elements || elements.length === 0) return [];
|
|
11854
|
+
const lines = [];
|
|
11855
|
+
let index = 0;
|
|
11856
|
+
for (const el of elements) {
|
|
11857
|
+
const content = el.content?.trim();
|
|
11858
|
+
if (!content) continue;
|
|
11859
|
+
index += 1;
|
|
11860
|
+
const author = el.author;
|
|
11861
|
+
const sender = author?.username ?? "\u672A\u77E5";
|
|
11862
|
+
lines.push(
|
|
11863
|
+
`=== \u6D88\u606F ${index} ===`,
|
|
11864
|
+
`[\u6D88\u606F\u5185\u5BB9] ${content}`,
|
|
11865
|
+
`[\u53D1\u9001\u8005] ${sender}`
|
|
11866
|
+
);
|
|
11867
|
+
}
|
|
11868
|
+
return lines;
|
|
11869
|
+
}
|
|
11841
11870
|
function unique(arr) {
|
|
11842
11871
|
return [...new Set(arr)];
|
|
11843
11872
|
}
|
|
@@ -11854,7 +11883,7 @@ function buildAgentBody(input) {
|
|
|
11854
11883
|
const label = formatSenderLabel(h2.senderName, h2.senderId);
|
|
11855
11884
|
return `[${label}] ${h2.content}`;
|
|
11856
11885
|
}).join("\n");
|
|
11857
|
-
return [
|
|
11886
|
+
return [HISTORY_BEGIN, historyText, "", HISTORY_END, CURRENT_MSG, base].join("\n");
|
|
11858
11887
|
}
|
|
11859
11888
|
return base;
|
|
11860
11889
|
}
|
|
@@ -11921,8 +11950,11 @@ function getHistoryStore() {
|
|
|
11921
11950
|
if (!_store) _store = new MemoryHistoryStore();
|
|
11922
11951
|
return _store;
|
|
11923
11952
|
}
|
|
11924
|
-
function
|
|
11925
|
-
|
|
11953
|
+
function historyGroupKey(accountId, groupId) {
|
|
11954
|
+
return `${accountId}:${groupId}`;
|
|
11955
|
+
}
|
|
11956
|
+
function clearGroupHistory(accountId, groupId) {
|
|
11957
|
+
_store?.clear?.(historyGroupKey(accountId, groupId));
|
|
11926
11958
|
}
|
|
11927
11959
|
|
|
11928
11960
|
// src/middleware/access-control.ts
|
|
@@ -12015,6 +12047,14 @@ function setupMiddlewares(bot, account, opts) {
|
|
|
12015
12047
|
bot.use(errorHandler());
|
|
12016
12048
|
bot.use(messageFilter({ skipSelfEcho: false }));
|
|
12017
12049
|
bot.use(createPolicyInjector(account));
|
|
12050
|
+
bot.use(historyBuffer({
|
|
12051
|
+
store: getHistoryStore(),
|
|
12052
|
+
groupKey: (ctx) => {
|
|
12053
|
+
const gid = ctx.message.groupOpenid;
|
|
12054
|
+
if (ctx.message.kind !== "group" || !gid) return void 0;
|
|
12055
|
+
return historyGroupKey(account.accountId, gid);
|
|
12056
|
+
}
|
|
12057
|
+
}));
|
|
12018
12058
|
bot.use(dynamicAccessControl({
|
|
12019
12059
|
accountId: account.accountId,
|
|
12020
12060
|
getRuntime: opts.getRuntime
|
|
@@ -12041,7 +12081,6 @@ function setupMiddlewares(bot, account, opts) {
|
|
|
12041
12081
|
bot.use(quoteRef({
|
|
12042
12082
|
store: getPersistedRefIndexStore(account.accountId)
|
|
12043
12083
|
}));
|
|
12044
|
-
bot.use(historyBuffer({ store: getHistoryStore() }));
|
|
12045
12084
|
bot.use(attachmentProcessor({ getRuntime: opts.getRuntime }));
|
|
12046
12085
|
bot.use(envelopeFormatter({
|
|
12047
12086
|
format: (ctx) => {
|
|
@@ -12209,6 +12248,77 @@ async function handleVoiceIntent(text, ctx) {
|
|
|
12209
12248
|
}
|
|
12210
12249
|
}
|
|
12211
12250
|
|
|
12251
|
+
// src/dispatch/ctx-builder.ts
|
|
12252
|
+
function buildCtxPayload(params) {
|
|
12253
|
+
const { assembled, envelope, route, msg, ctx, adapters } = params;
|
|
12254
|
+
const isSlashCommand = /^\//.test(assembled.rawBody ?? "");
|
|
12255
|
+
const convKind = envelope.chatScope === "group" ? "group" : "direct";
|
|
12256
|
+
const peerId = convKind === "group" ? envelope.groupId ?? envelope.senderId : envelope.senderId;
|
|
12257
|
+
const groupId = convKind === "group" ? envelope.groupId : void 0;
|
|
12258
|
+
const processed = ctx.state.processedAttachments;
|
|
12259
|
+
const voicePaths = processed?.localMediaPaths?.filter((_2, i) => processed.localMediaTypes?.[i]?.startsWith("audio/")) ?? [];
|
|
12260
|
+
const voiceUrls = processed?.remoteMediaUrls?.filter((_2, i) => processed.remoteMediaUrls?.[i]?.startsWith?.("audio/")) ?? [];
|
|
12261
|
+
const msgTimestamp = msg.timestamp ?? msg.Timestamp;
|
|
12262
|
+
return adapters.buildInboundContext?.({
|
|
12263
|
+
channel: "qqbot",
|
|
12264
|
+
accountId: route.accountId,
|
|
12265
|
+
provider: "qqbot",
|
|
12266
|
+
surface: "qqbot",
|
|
12267
|
+
messageId: envelope.messageId,
|
|
12268
|
+
timestamp: msgTimestamp ? new Date(msgTimestamp).getTime() : Date.now(),
|
|
12269
|
+
from: envelope.targetId,
|
|
12270
|
+
sender: { id: envelope.senderId, name: envelope.senderName },
|
|
12271
|
+
conversation: {
|
|
12272
|
+
kind: convKind,
|
|
12273
|
+
id: peerId,
|
|
12274
|
+
label: assembled.systemPrompt
|
|
12275
|
+
},
|
|
12276
|
+
message: {
|
|
12277
|
+
body: assembled.webBody,
|
|
12278
|
+
bodyForAgent: assembled.agentBody,
|
|
12279
|
+
rawBody: assembled.rawBody,
|
|
12280
|
+
commandBody: assembled.rawBody
|
|
12281
|
+
},
|
|
12282
|
+
route: {
|
|
12283
|
+
agentId: route.agentId ?? "default",
|
|
12284
|
+
routeSessionKey: route.sessionKey,
|
|
12285
|
+
accountId: route.accountId
|
|
12286
|
+
},
|
|
12287
|
+
reply: {
|
|
12288
|
+
to: envelope.targetId,
|
|
12289
|
+
replyToId: envelope.messageId,
|
|
12290
|
+
originatingTo: envelope.targetId
|
|
12291
|
+
},
|
|
12292
|
+
access: {
|
|
12293
|
+
commands: { authorized: isSlashCommand }
|
|
12294
|
+
},
|
|
12295
|
+
command: isSlashCommand ? { kind: "text-slash", body: assembled.rawBody, authorized: true } : void 0,
|
|
12296
|
+
media: voicePaths.length > 0 ? voicePaths.map((p2, i) => ({
|
|
12297
|
+
contentType: processed?.localMediaTypes?.[i] ?? "audio/silk",
|
|
12298
|
+
localPath: p2,
|
|
12299
|
+
url: voiceUrls[i]
|
|
12300
|
+
})) : voiceUrls.length > 0 ? voiceUrls.map((u2) => ({ contentType: "audio/wav", url: u2 })) : void 0,
|
|
12301
|
+
supplemental: {
|
|
12302
|
+
quote: envelope.quote ? { id: envelope.messageId, body: envelope.quote.content, sender: envelope.quote.senderId } : void 0,
|
|
12303
|
+
groupSystemPrompt: envelope.systemPrompt
|
|
12304
|
+
},
|
|
12305
|
+
extra: {
|
|
12306
|
+
...isSlashCommand ? { CommandSource: "text" } : {},
|
|
12307
|
+
...groupId ? { QQGroupOpenid: groupId } : {},
|
|
12308
|
+
...processed?.localMediaPaths?.length ? {
|
|
12309
|
+
MediaPaths: processed.localMediaPaths,
|
|
12310
|
+
MediaPath: processed.localMediaPaths[0],
|
|
12311
|
+
MediaTypes: processed.localMediaTypes,
|
|
12312
|
+
MediaType: processed.localMediaTypes?.[0]
|
|
12313
|
+
} : {},
|
|
12314
|
+
...processed?.remoteMediaUrls?.length ? {
|
|
12315
|
+
MediaUrls: processed.remoteMediaUrls,
|
|
12316
|
+
MediaUrl: processed.remoteMediaUrls[0]
|
|
12317
|
+
} : {}
|
|
12318
|
+
}
|
|
12319
|
+
});
|
|
12320
|
+
}
|
|
12321
|
+
|
|
12212
12322
|
// src/outbound/debounce.ts
|
|
12213
12323
|
var DEFAULT_WINDOW_MS = 1500;
|
|
12214
12324
|
var DEFAULT_MAX_WAIT_MS = 8e3;
|
|
@@ -12446,46 +12556,7 @@ async function dispatchToOpenClaw(ctx, msg, account, runtime2, log4) {
|
|
|
12446
12556
|
const qualifiedTarget = envelope.targetId;
|
|
12447
12557
|
const agentId = route.agentId ?? "default";
|
|
12448
12558
|
const storePath = adapters.resolveStorePath?.(cfg?.session?.store, { agentId }) ?? "";
|
|
12449
|
-
const ctxPayload =
|
|
12450
|
-
channel: "qqbot",
|
|
12451
|
-
accountId: route.accountId,
|
|
12452
|
-
provider: "qqbot",
|
|
12453
|
-
surface: "qqbot",
|
|
12454
|
-
messageId: envelope.messageId,
|
|
12455
|
-
timestamp: Date.now(),
|
|
12456
|
-
from: envelope.targetId,
|
|
12457
|
-
sender: { id: envelope.senderId, name: envelope.senderName },
|
|
12458
|
-
conversation: {
|
|
12459
|
-
kind: envelope.chatScope === "group" ? "group" : "direct",
|
|
12460
|
-
label: assembled.systemPrompt
|
|
12461
|
-
},
|
|
12462
|
-
message: {
|
|
12463
|
-
body: assembled.webBody,
|
|
12464
|
-
bodyForAgent: assembled.agentBody,
|
|
12465
|
-
rawBody: assembled.rawBody,
|
|
12466
|
-
commandBody: assembled.rawBody
|
|
12467
|
-
},
|
|
12468
|
-
route: {
|
|
12469
|
-
routeSessionKey: route.sessionKey,
|
|
12470
|
-
accountId: route.accountId
|
|
12471
|
-
},
|
|
12472
|
-
reply: {
|
|
12473
|
-
to: envelope.targetId,
|
|
12474
|
-
replyToId: envelope.messageId,
|
|
12475
|
-
originatingTo: envelope.targetId
|
|
12476
|
-
}
|
|
12477
|
-
});
|
|
12478
|
-
const processed = ctx.state.processedAttachments;
|
|
12479
|
-
if (processed?.localMediaPaths?.length) {
|
|
12480
|
-
ctxPayload.MediaPaths = processed.localMediaPaths;
|
|
12481
|
-
ctxPayload.MediaPath = processed.localMediaPaths[0];
|
|
12482
|
-
ctxPayload.MediaTypes = processed.localMediaTypes;
|
|
12483
|
-
ctxPayload.MediaType = processed.localMediaTypes?.[0];
|
|
12484
|
-
}
|
|
12485
|
-
if (processed?.remoteMediaUrls?.length) {
|
|
12486
|
-
ctxPayload.MediaUrls = processed.remoteMediaUrls;
|
|
12487
|
-
ctxPayload.MediaUrl = processed.remoteMediaUrls[0];
|
|
12488
|
-
}
|
|
12559
|
+
const ctxPayload = buildCtxPayload({ assembled, envelope, route, msg, ctx, adapters });
|
|
12489
12560
|
const ttsRuntime = runtime2?.tts ?? runtime2?.channel?.runtimeContexts?.get?.("tts");
|
|
12490
12561
|
const debounceConfig = account.config?.deliverDebounce;
|
|
12491
12562
|
const debouncer = debounceConfig?.enabled !== false ? new DeliverDebouncer(
|
|
@@ -12679,7 +12750,7 @@ async function dispatchToOpenClaw(ctx, msg, account, runtime2, log4) {
|
|
|
12679
12750
|
}
|
|
12680
12751
|
dlog?.debug(`inboundRun completed sessionKey=${route.sessionKey}`);
|
|
12681
12752
|
if (envelope.chatScope === "group") {
|
|
12682
|
-
clearGroupHistory(envelope.groupId ?? envelope.senderId);
|
|
12753
|
+
clearGroupHistory(account.accountId, envelope.groupId ?? envelope.senderId);
|
|
12683
12754
|
}
|
|
12684
12755
|
if (streamingController && !streamingController.isTerminal) {
|
|
12685
12756
|
await streamingController.finalize();
|