@cxyhhhhh/openclaw-qqbot 2.0.0-dev.202607082219 → 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 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 = 50;
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.202607082219" : "unknown";
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);
@@ -9590,6 +9593,8 @@ function resolveRuntimeAdapters(rt, log4) {
9590
9593
  ["config", "current"]
9591
9594
  ]) ?? probeFunction(rt, [
9592
9595
  ["getConfig"]
9596
+ ]) ?? probeFunction(rt, [
9597
+ ["config", "loadConfig"]
9593
9598
  ]);
9594
9599
  const rawMutateConfig = probeFunction(rt, [["config", "mutateConfigFile"]]);
9595
9600
  const rawWriteConfig = probeFunction(rt, [["config", "writeConfigFile"]]);
@@ -11710,10 +11715,13 @@ async function downloadMediaFile(url, filename, log4) {
11710
11715
  // src/dispatch/body-assembler.ts
11711
11716
  var QUOTE_BEGIN = "[Quoted message begins]";
11712
11717
  var QUOTE_END = "[Quoted message ends]";
11713
- var HISTORY_CTX_START = "[Chat messages since your last reply \u2014 CONTEXT ONLY]";
11714
- var HISTORY_CTX_END = "[CURRENT MESSAGE \u2014 reply to this]";
11715
- var MERGE_CTX_START = "[Merged messages \u2014 CONTEXT ONLY]";
11716
- var MERGE_CTX_END = "[CURRENT MESSAGE \u2014 reply to this one]";
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]";
11717
11725
  function assembleBody(ctx, msg, account, getRuntime) {
11718
11726
  const rawBody = msg.content ?? "";
11719
11727
  const isGroup = msg.kind === "group";
@@ -11726,7 +11734,7 @@ function assembleBody(ctx, msg, account, getRuntime) {
11726
11734
  const userContent = buildUserContent(ctx.message.content ?? "", processed);
11727
11735
  const quotePart = buildQuotePart(quote);
11728
11736
  const userMessage = mergedMessages && mergedMessages.length > 0 ? buildMergedUserMessage({ messages: mergedMessages, quotePart, isGroup, wasMentioned, getRuntime }) : buildUserMessage({ msg, userContent, quotePart, isGroup, wasMentioned });
11729
- const dynamicCtx = buildDynamicCtx(processed);
11737
+ const dynamicCtx = buildDynamicCtx(processed, msg, quote);
11730
11738
  const agentBody = buildAgentBody({
11731
11739
  userContent,
11732
11740
  base: dynamicCtx + userMessage,
@@ -11752,12 +11760,11 @@ ${voiceText}` : voiceText) + attachmentInfo;
11752
11760
  }
11753
11761
  function buildQuotePart(quote) {
11754
11762
  if (!quote) return "";
11755
- const sender = quote.entry?.senderName ? `${quote.entry.senderName} (${quote.entry.senderId})` : "";
11756
- const senderLine = sender ? `${sender}: ` : "";
11757
11763
  const text = quote.text || "Original content unavailable";
11758
11764
  return `${QUOTE_BEGIN}
11759
- ${senderLine}${text}
11765
+ ${text}
11760
11766
  ${QUOTE_END}
11767
+ ${CURRENT_MSG}
11761
11768
  `;
11762
11769
  }
11763
11770
  function buildUserMessage(input) {
@@ -11765,7 +11772,7 @@ function buildUserMessage(input) {
11765
11772
  const atYouTag = isGroup && wasMentioned ? " (@you)" : "";
11766
11773
  if (isGroup) {
11767
11774
  const senderLabel = formatSenderLabel(msg.senderName, msg.senderId);
11768
- return `[${senderLabel}] ${quotePart}${userContent}${atYouTag}`;
11775
+ return `${quotePart}[${senderLabel}] ${userContent}${atYouTag}`;
11769
11776
  }
11770
11777
  return `${quotePart}${userContent}`;
11771
11778
  }
@@ -11791,7 +11798,7 @@ function buildMergedUserMessage(input) {
11791
11798
  return lines.join("\n");
11792
11799
  }
11793
11800
  const last = lines.pop();
11794
- return [MERGE_CTX_START, ...lines, MERGE_CTX_END, last].join("\n");
11801
+ return [MERGE_CTX_BEGIN, ...lines, MERGE_CTX_END, CURRENT_MSG, last].join("\n");
11795
11802
  }
11796
11803
  function formatMergedLine(ctx, opts) {
11797
11804
  const m3 = ctx.message;
@@ -11812,13 +11819,12 @@ function allSameSender(messages) {
11812
11819
  const first = messages[0]?.message.senderId;
11813
11820
  return messages.every((c) => c.message.senderId === first);
11814
11821
  }
11815
- function buildDynamicCtx(processed) {
11816
- if (!processed) return "";
11822
+ function buildDynamicCtx(processed, msg, quote) {
11817
11823
  const lines = [];
11818
- if (processed.imageUrls.length > 0) {
11824
+ if (processed?.imageUrls.length) {
11819
11825
  lines.push(`- Images: ${processed.imageUrls.join(", ")}`);
11820
11826
  }
11821
- const transcripts = processed.transcripts ?? [];
11827
+ const transcripts = processed?.transcripts ?? [];
11822
11828
  const voiceRefs = unique([
11823
11829
  ...transcripts.map((t) => t.localPath).filter(isNonEmpty),
11824
11830
  ...transcripts.map((t) => t.remoteUrl).filter(isNonEmpty)
@@ -11832,10 +11838,35 @@ function buildDynamicCtx(processed) {
11832
11838
  if (asrTexts.length > 0) {
11833
11839
  lines.push(`- ASR: ${asrTexts.join(" | ")}`);
11834
11840
  }
11841
+ if (!quote) {
11842
+ const elementsCtx = buildMsgElementsContext(msg);
11843
+ if (elementsCtx.length > 0) {
11844
+ lines.push(REF_BEGIN, ...elementsCtx, REF_END);
11845
+ }
11846
+ }
11835
11847
  return lines.length > 0 ? `${lines.join("\n")}
11836
11848
 
11837
11849
  ` : "";
11838
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
+ }
11839
11870
  function unique(arr) {
11840
11871
  return [...new Set(arr)];
11841
11872
  }
@@ -11852,7 +11883,7 @@ function buildAgentBody(input) {
11852
11883
  const label = formatSenderLabel(h2.senderName, h2.senderId);
11853
11884
  return `[${label}] ${h2.content}`;
11854
11885
  }).join("\n");
11855
- return [HISTORY_CTX_START, historyText, "", HISTORY_CTX_END, base].join("\n");
11886
+ return [HISTORY_BEGIN, historyText, "", HISTORY_END, CURRENT_MSG, base].join("\n");
11856
11887
  }
11857
11888
  return base;
11858
11889
  }
@@ -11919,8 +11950,11 @@ function getHistoryStore() {
11919
11950
  if (!_store) _store = new MemoryHistoryStore();
11920
11951
  return _store;
11921
11952
  }
11922
- function clearGroupHistory(groupId) {
11923
- _store?.clear?.(groupId);
11953
+ function historyGroupKey(accountId, groupId) {
11954
+ return `${accountId}:${groupId}`;
11955
+ }
11956
+ function clearGroupHistory(accountId, groupId) {
11957
+ _store?.clear?.(historyGroupKey(accountId, groupId));
11924
11958
  }
11925
11959
 
11926
11960
  // src/middleware/access-control.ts
@@ -12013,6 +12047,14 @@ function setupMiddlewares(bot, account, opts) {
12013
12047
  bot.use(errorHandler());
12014
12048
  bot.use(messageFilter({ skipSelfEcho: false }));
12015
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
+ }));
12016
12058
  bot.use(dynamicAccessControl({
12017
12059
  accountId: account.accountId,
12018
12060
  getRuntime: opts.getRuntime
@@ -12039,7 +12081,6 @@ function setupMiddlewares(bot, account, opts) {
12039
12081
  bot.use(quoteRef({
12040
12082
  store: getPersistedRefIndexStore(account.accountId)
12041
12083
  }));
12042
- bot.use(historyBuffer({ store: getHistoryStore() }));
12043
12084
  bot.use(attachmentProcessor({ getRuntime: opts.getRuntime }));
12044
12085
  bot.use(envelopeFormatter({
12045
12086
  format: (ctx) => {
@@ -12207,6 +12248,77 @@ async function handleVoiceIntent(text, ctx) {
12207
12248
  }
12208
12249
  }
12209
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
+
12210
12322
  // src/outbound/debounce.ts
12211
12323
  var DEFAULT_WINDOW_MS = 1500;
12212
12324
  var DEFAULT_MAX_WAIT_MS = 8e3;
@@ -12444,46 +12556,7 @@ async function dispatchToOpenClaw(ctx, msg, account, runtime2, log4) {
12444
12556
  const qualifiedTarget = envelope.targetId;
12445
12557
  const agentId = route.agentId ?? "default";
12446
12558
  const storePath = adapters.resolveStorePath?.(cfg?.session?.store, { agentId }) ?? "";
12447
- const ctxPayload = adapters.buildInboundContext?.({
12448
- channel: "qqbot",
12449
- accountId: route.accountId,
12450
- provider: "qqbot",
12451
- surface: "qqbot",
12452
- messageId: envelope.messageId,
12453
- timestamp: Date.now(),
12454
- from: envelope.targetId,
12455
- sender: { id: envelope.senderId, name: envelope.senderName },
12456
- conversation: {
12457
- kind: envelope.chatScope === "group" ? "group" : "direct",
12458
- label: assembled.systemPrompt
12459
- },
12460
- message: {
12461
- body: assembled.webBody,
12462
- bodyForAgent: assembled.agentBody,
12463
- rawBody: assembled.rawBody,
12464
- commandBody: assembled.rawBody
12465
- },
12466
- route: {
12467
- routeSessionKey: route.sessionKey,
12468
- accountId: route.accountId
12469
- },
12470
- reply: {
12471
- to: envelope.targetId,
12472
- replyToId: envelope.messageId,
12473
- originatingTo: envelope.targetId
12474
- }
12475
- });
12476
- const processed = ctx.state.processedAttachments;
12477
- if (processed?.localMediaPaths?.length) {
12478
- ctxPayload.MediaPaths = processed.localMediaPaths;
12479
- ctxPayload.MediaPath = processed.localMediaPaths[0];
12480
- ctxPayload.MediaTypes = processed.localMediaTypes;
12481
- ctxPayload.MediaType = processed.localMediaTypes?.[0];
12482
- }
12483
- if (processed?.remoteMediaUrls?.length) {
12484
- ctxPayload.MediaUrls = processed.remoteMediaUrls;
12485
- ctxPayload.MediaUrl = processed.remoteMediaUrls[0];
12486
- }
12559
+ const ctxPayload = buildCtxPayload({ assembled, envelope, route, msg, ctx, adapters });
12487
12560
  const ttsRuntime = runtime2?.tts ?? runtime2?.channel?.runtimeContexts?.get?.("tts");
12488
12561
  const debounceConfig = account.config?.deliverDebounce;
12489
12562
  const debouncer = debounceConfig?.enabled !== false ? new DeliverDebouncer(
@@ -12677,7 +12750,7 @@ async function dispatchToOpenClaw(ctx, msg, account, runtime2, log4) {
12677
12750
  }
12678
12751
  dlog?.debug(`inboundRun completed sessionKey=${route.sessionKey}`);
12679
12752
  if (envelope.chatScope === "group") {
12680
- clearGroupHistory(envelope.groupId ?? envelope.senderId);
12753
+ clearGroupHistory(account.accountId, envelope.groupId ?? envelope.senderId);
12681
12754
  }
12682
12755
  if (streamingController && !streamingController.isTerminal) {
12683
12756
  await streamingController.finalize();