openclaw-plugin-yuanbao 2.0.0 → 2.0.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.
@@ -2,7 +2,7 @@
2
2
  "id": "openclaw-plugin-yuanbao",
3
3
  "name": "元宝 Bot",
4
4
  "description": "Tencent YuanBao intelligent bot channel plugin",
5
- "version": "2.0.0",
5
+ "version": "2.0.1",
6
6
  "channels": [
7
7
  "yuanbao"
8
8
  ],
@@ -8,8 +8,8 @@ import { startYuanbaoWsGateway, getActiveWsClient } from './yuanbao-server/ws/in
8
8
  import { getYuanbaoRuntime } from './runtime.js';
9
9
  import { sendYuanbaoMessage, sendYuanbaoGroupMessage } from './message-handler/index.js';
10
10
  import { initOutboundQueue, destroyOutboundQueue, getOutboundQueue } from './outbound-queue.js';
11
- import { parseTarget, looksLikeYuanbaoId, sendDM, resolveUsername, } from './dm/index.js';
12
- import { yuanbaoMessageActions } from './channel-actions.js';
11
+ import { parseTarget, sendDM, } from './dm/index.js';
12
+ import { yuanbaoMessageActions } from './message-tool/index.js';
13
13
  function toChannelResult(result) {
14
14
  return {
15
15
  channel: 'yuanbao',
@@ -31,6 +31,9 @@ async function sendTextToTarget(account, target, text, wsClient) {
31
31
  if (target.startsWith('group:')) {
32
32
  return sendYuanbaoGroupMessage({ account, groupCode: target.slice('group:'.length), text, fromAccount: account.botId, ctx: minCtx });
33
33
  }
34
+ if (target.startsWith('direct:')) {
35
+ return sendYuanbaoMessage({ account, toAccount: target.slice('direct:'.length), text, fromAccount: account.botId, ctx: minCtx });
36
+ }
34
37
  return sendYuanbaoMessage({ account, toAccount: target, text, fromAccount: account.botId, ctx: minCtx });
35
38
  }
36
39
  const meta = {
@@ -142,34 +145,8 @@ export const yuanbaoPlugin = {
142
145
  messaging: {
143
146
  normalizeTarget: normalizeYuanbaoMessagingTarget,
144
147
  targetResolver: {
145
- looksLikeId: (raw, normalized) => {
146
- const trimmed = raw.trim();
147
- const norm = normalized?.trim() ?? trimmed;
148
- return looksLikeYuanbaoId(trimmed)
149
- || trimmed.startsWith('user:')
150
- || trimmed.startsWith('group:')
151
- || trimmed.startsWith('@')
152
- || looksLikeYuanbaoId(norm)
153
- || norm.startsWith('user:')
154
- || norm.startsWith('group:')
155
- || norm.startsWith('@');
156
- },
157
- hint: '<user:ID | @username | group:groupId>',
158
- async resolveTarget({ input, accountId }) {
159
- const target = parseTarget(input);
160
- if (!target)
161
- return null;
162
- if (target.kind === 'user') {
163
- if (!looksLikeYuanbaoId(target.id)) {
164
- const resolved = resolveUsername(target.id, accountId);
165
- if (!resolved)
166
- return null;
167
- return { to: `user:${resolved.id}`, kind: 'user', display: resolved.name };
168
- }
169
- return { to: `user:${target.id}`, kind: 'user' };
170
- }
171
- return { to: `group:${target.id}`, kind: target.kind };
172
- },
148
+ looksLikeId: raw => Boolean(raw.trim()),
149
+ hint: '<userid> or group:<groupcode>',
173
150
  },
174
151
  },
175
152
  outbound: {
@@ -177,7 +154,8 @@ export const yuanbaoPlugin = {
177
154
  chunkerMode: 'text',
178
155
  textChunkLimit: 3000,
179
156
  chunker: (text, limit) => getYuanbaoRuntime()?.channel.text.chunkMarkdownText(text, limit) ?? [text],
180
- sendText: async ({ cfg, to, text, accountId }) => {
157
+ sendText: async ({ cfg, to: _to, text, accountId }) => {
158
+ const to = _to.replace(/^yuanbao:/, '');
181
159
  const account = resolveYuanbaoAccount({ cfg, accountId: accountId ?? undefined });
182
160
  const dmTarget = parseTarget(to);
183
161
  if (dmTarget?.kind === 'user') {
@@ -197,7 +175,8 @@ export const yuanbaoPlugin = {
197
175
  }
198
176
  const queueManager = getOutboundQueue(account.accountId);
199
177
  if (queueManager) {
200
- const session = queueManager.getSession(to);
178
+ const safeTo = to.replace(/^user:/, 'direct:');
179
+ const session = queueManager.getSession(safeTo);
201
180
  if (session) {
202
181
  await session.push({ type: 'text', text });
203
182
  return { channel: 'yuanbao', ok: true, messageId: '' };
@@ -206,7 +185,8 @@ export const yuanbaoPlugin = {
206
185
  }
207
186
  return toChannelResult(await sendTextToTarget(account, to, text, wsClient));
208
187
  },
209
- sendMedia: async ({ cfg, accountId, to, mediaUrl, text }) => {
188
+ sendMedia: async ({ cfg, accountId, to: _to, mediaUrl, text }) => {
189
+ const to = _to.replace(/^yuanbao:/, '');
210
190
  const account = resolveYuanbaoAccount({ cfg, accountId: accountId ?? undefined });
211
191
  const wsClient = getActiveWsClient(account.accountId);
212
192
  if (!wsClient) {
@@ -217,7 +197,8 @@ export const yuanbaoPlugin = {
217
197
  }
218
198
  const queueManager = getOutboundQueue(account.accountId);
219
199
  if (queueManager) {
220
- const session = queueManager.getSession(to);
200
+ const safeTo = to.replace(/^user:/, 'direct:');
201
+ const session = queueManager.getSession(safeTo);
221
202
  if (session) {
222
203
  await session.push({ type: 'text', text });
223
204
  await session.push({ type: 'media', mediaUrl });
@@ -23,7 +23,8 @@ export function supportsAction(action) {
23
23
  return action === 'send';
24
24
  }
25
25
  export async function handleAction(ctx) {
26
- if (ctx.action !== 'send') {
26
+ if (ctx.action !== 'send'
27
+ || !ctx.toolContext?.currentChannelId.includes('group:')) {
27
28
  return null;
28
29
  }
29
30
  const log = createLog('dm:action');
@@ -51,6 +52,7 @@ export async function handleAction(ctx) {
51
52
  });
52
53
  }
53
54
  if (target.kind === 'user') {
55
+ console.log('handleAction DM', ctx);
54
56
  const senderId = ctx.requesterSenderId ?? '';
55
57
  const accessResult = enforceDMAccess(senderId, target.id, message.length, DEFAULT_DM_ACCESS_POLICY);
56
58
  if (!accessResult.allowed) {
@@ -0,0 +1,4 @@
1
+ import type { YuanbaoInboundMessage } from '../../types.js';
2
+ import type { MessageHandlerContext } from '../context.js';
3
+ export declare function handleGroupRecall(ctx: MessageHandlerContext, msg: YuanbaoInboundMessage): void;
4
+ export declare function handleC2CRecall(ctx: MessageHandlerContext, msg: YuanbaoInboundMessage): void;
@@ -0,0 +1,90 @@
1
+ import { chatHistories } from '../chat-history.js';
2
+ import { createLog } from '../../logger.js';
3
+ function enqueueRecallSystemEvent(params) {
4
+ const { core, sessionKey, conversationId, messageId } = params;
5
+ const eventText = [
6
+ `[yuanbao] One historical user message was recalled; only message_id="${messageId}" is void (not necessarily the latest turn).`,
7
+ 'Do not quote or ground on it; ignore stale transcript for that id. Keep past assistant replies; no tool rollback.',
8
+ ].join('\n');
9
+ core.system.enqueueSystemEvent(eventText, {
10
+ sessionKey,
11
+ contextKey: `yuanbao:recall:${conversationId}:${messageId}`,
12
+ });
13
+ }
14
+ export function handleGroupRecall(ctx, msg) {
15
+ const { core, account } = ctx;
16
+ const log = createLog('recall', ctx.log);
17
+ const groupCode = msg.group_code?.trim() || 'unknown';
18
+ const seqList = msg.recall_msg_seq_list;
19
+ if (!seqList || seqList.length === 0) {
20
+ log.warn('[recall] group msg_seq_list 为空,跳过');
21
+ return;
22
+ }
23
+ const route = core.channel.routing.resolveAgentRoute({
24
+ cfg: ctx.config,
25
+ channel: 'yuanbao',
26
+ accountId: account.accountId,
27
+ peer: { kind: 'group', id: groupCode },
28
+ });
29
+ const where = msg.group_name
30
+ ? `group "${msg.group_name}" (${groupCode})`
31
+ : `group ${groupCode}`;
32
+ for (const seq of seqList) {
33
+ const messageId = seq.msg_id || String(seq.msg_seq ?? '');
34
+ if (!messageId)
35
+ continue;
36
+ const history = chatHistories.get(groupCode);
37
+ const idx = history
38
+ ? history.findIndex(e => e.messageId === messageId)
39
+ : -1;
40
+ if (history && idx !== -1) {
41
+ history.splice(idx, 1);
42
+ log.info(`[recall] 群消息 ${messageId} 已从 history 删除(未被 AI 消费)`, { groupCode });
43
+ }
44
+ else {
45
+ log.info(`[recall] 群消息 ${messageId} 不在 history,注入系统事件`, {
46
+ groupCode,
47
+ });
48
+ enqueueRecallSystemEvent({
49
+ core,
50
+ sessionKey: route.sessionKey,
51
+ conversationId: groupCode,
52
+ where,
53
+ messageId,
54
+ });
55
+ }
56
+ }
57
+ }
58
+ export function handleC2CRecall(ctx, msg) {
59
+ const { core, account } = ctx;
60
+ const log = createLog('recall', ctx.log);
61
+ const fromAccount = msg.from_account?.trim() || 'unknown';
62
+ const seqList = msg.msg_id
63
+ ? [{ msg_id: msg.msg_id, msg_seq: msg.msg_seq }]
64
+ : [];
65
+ if (!seqList || seqList.length === 0) {
66
+ log.warn('[recall] c2c msg_seq_list 为空,跳过');
67
+ return;
68
+ }
69
+ const route = core.channel.routing.resolveAgentRoute({
70
+ cfg: ctx.config,
71
+ channel: 'yuanbao',
72
+ accountId: account.accountId,
73
+ peer: { kind: 'direct', id: fromAccount },
74
+ });
75
+ for (const seq of seqList) {
76
+ const messageId = seq.msg_id || String(seq.msg_seq ?? '');
77
+ if (!messageId)
78
+ continue;
79
+ log.info(`[recall] C2C 消息 ${messageId} 被撤回,注入系统事件`, {
80
+ fromAccount,
81
+ });
82
+ enqueueRecallSystemEvent({
83
+ core,
84
+ sessionKey: route.sessionKey,
85
+ conversationId: fromAccount,
86
+ where: `direct chat with ${fromAccount}`,
87
+ messageId,
88
+ });
89
+ }
90
+ }
@@ -0,0 +1,19 @@
1
+ import type { HistoryEntry } from 'openclaw/plugin-sdk/reply-history';
2
+ export type GroupHistoryEntry = HistoryEntry & {
3
+ medias?: Array<{
4
+ url: string;
5
+ mediaName?: string;
6
+ }>;
7
+ };
8
+ export type MediaHistoryEntry = {
9
+ sender: string;
10
+ messageId?: string;
11
+ timestamp: number;
12
+ medias: Array<{
13
+ url: string;
14
+ mediaName?: string;
15
+ }>;
16
+ };
17
+ export declare const chatHistories: Map<string, GroupHistoryEntry[]>;
18
+ export declare const chatMediaHistories: Map<string, MediaHistoryEntry[]>;
19
+ export declare function recordMediaHistory(groupCode: string, entry: MediaHistoryEntry): void;
@@ -0,0 +1,16 @@
1
+ export const chatHistories = new Map();
2
+ const MEDIA_HISTORY_MAX_PER_GROUP = 50;
3
+ export const chatMediaHistories = new Map();
4
+ export function recordMediaHistory(groupCode, entry) {
5
+ if (entry.medias.length === 0)
6
+ return;
7
+ let list = chatMediaHistories.get(groupCode);
8
+ if (!list) {
9
+ list = [];
10
+ chatMediaHistories.set(groupCode, list);
11
+ }
12
+ list.push(entry);
13
+ if (list.length > MEDIA_HISTORY_MAX_PER_GROUP) {
14
+ list.splice(0, list.length - MEDIA_HISTORY_MAX_PER_GROUP);
15
+ }
16
+ }
@@ -32,7 +32,6 @@ export function buildMsgBody(msgType, data) {
32
32
  const handler = handlerMap.get(msgType);
33
33
  return handler?.buildMsgBody?.(data);
34
34
  }
35
- const INLINE_IMAGE_RE = /!\[([^\]]*)\]\(([^)]+)\)/g;
36
35
  const AT_USER_RE = /(?<=\s|^)@(\S+?)(?=\s|$)/g;
37
36
  function resolveAtMentions(text, groupCode, memberInst) {
38
37
  const items = [];
@@ -77,20 +76,8 @@ export function prepareOutboundContent(text, groupCode, memberInst) {
77
76
  if (!text)
78
77
  return [];
79
78
  const items = [];
80
- let lastIndex = 0;
81
- for (const match of text.matchAll(INLINE_IMAGE_RE)) {
82
- const matchStart = match.index;
83
- if (matchStart > lastIndex) {
84
- const before = text.slice(lastIndex, matchStart).trim();
85
- if (before) {
86
- items.push(...resolveAtMentions(before, groupCode, memberInst));
87
- }
88
- }
89
- items.push({ type: 'image', url: match[2] });
90
- lastIndex = matchStart + match[0].length;
91
- }
92
- if (lastIndex < text.length) {
93
- const trailing = text.slice(lastIndex).trim();
79
+ if (text.length) {
80
+ const trailing = text.trim();
94
81
  if (trailing) {
95
82
  items.push(...resolveAtMentions(trailing, groupCode, memberInst));
96
83
  }
@@ -1,5 +1,6 @@
1
1
  import type { YuanbaoInboundMessage } from '../types.js';
2
2
  import type { MessageHandlerContext } from './context.js';
3
+ import './callbacks/recall.js';
3
4
  export declare function handleInboundMessage(params: {
4
5
  ctx: MessageHandlerContext;
5
6
  msg: YuanbaoInboundMessage;
@@ -11,22 +11,9 @@ import { getOutboundQueue } from '../outbound-queue.js';
11
11
  import { UPGRADE_COMMAND_NAMES } from '../commands/upgrade.js';
12
12
  import { sendStickerYuanbao } from '../sticker/sticker-sender.js';
13
13
  import { getCachedSticker } from '../sticker/sticker-cache.js';
14
- const chatHistories = new Map();
15
- const MEDIA_HISTORY_MAX_PER_GROUP = 50;
16
- const chatMediaHistories = new Map();
17
- function recordMediaHistory(groupCode, entry) {
18
- if (entry.medias.length === 0)
19
- return;
20
- let list = chatMediaHistories.get(groupCode);
21
- if (!list) {
22
- list = [];
23
- chatMediaHistories.set(groupCode, list);
24
- }
25
- list.push(entry);
26
- if (list.length > MEDIA_HISTORY_MAX_PER_GROUP) {
27
- list.splice(0, list.length - MEDIA_HISTORY_MAX_PER_GROUP);
28
- }
29
- }
14
+ import { dispatchSystemCallback } from './system-callbacks.js';
15
+ import { chatHistories, chatMediaHistories, recordMediaHistory, } from './chat-history.js';
16
+ import './callbacks/recall.js';
30
17
  const conversationQueues = new Map();
31
18
  function enqueueForConversation(key, task) {
32
19
  const prev = conversationQueues.get(key) ?? Promise.resolve();
@@ -577,6 +564,8 @@ async function handleGroupMessage(params) {
577
564
  }
578
565
  export async function handleInboundMessage(params) {
579
566
  const { ctx, msg, chatType } = params;
567
+ if (dispatchSystemCallback({ ctx, msg, chatType }))
568
+ return;
580
569
  const convKey = chatType === 'group'
581
570
  ? `group:${ctx.account.accountId}:${msg.group_code?.trim() || 'unknown'}`
582
571
  : `c2c:${ctx.account.accountId}:${msg.from_account?.trim() || 'unknown'}`;
@@ -3,5 +3,7 @@ export { extractTextFromMsgBody } from './extract.js';
3
3
  export type { ExtractTextFromMsgBodyResult } from './extract.js';
4
4
  export { sendYuanbaoMessage, sendYuanbaoGroupMessage, sendMsgBodyDirect, } from './outbound.js';
5
5
  export { handleInboundMessage } from './inbound.js';
6
+ export { registerSystemCallback } from './system-callbacks.js';
7
+ export type { SystemCallbackHandler, SystemCallbackParams } from './system-callbacks.js';
6
8
  export { getHandler, getAllHandlers, buildMsgBody, prepareOutboundContent, buildOutboundMsgBody, buildAtUserMsgBodyItem, textHandler, customHandler, imageHandler, soundHandler, fileHandler, videoHandler, } from './handlers/index.js';
7
9
  export type { MessageElemHandler, MsgBodyItemType, MediaItem, OutboundContentItem } from './handlers/index.js';
@@ -1,4 +1,5 @@
1
1
  export { extractTextFromMsgBody } from './extract.js';
2
2
  export { sendYuanbaoMessage, sendYuanbaoGroupMessage, sendMsgBodyDirect, } from './outbound.js';
3
3
  export { handleInboundMessage } from './inbound.js';
4
+ export { registerSystemCallback } from './system-callbacks.js';
4
5
  export { getHandler, getAllHandlers, buildMsgBody, prepareOutboundContent, buildOutboundMsgBody, buildAtUserMsgBodyItem, textHandler, customHandler, imageHandler, soundHandler, fileHandler, videoHandler, } from './handlers/index.js';
@@ -0,0 +1,10 @@
1
+ import type { YuanbaoInboundMessage } from '../types.js';
2
+ import type { MessageHandlerContext } from './context.js';
3
+ export type SystemCallbackParams = {
4
+ ctx: MessageHandlerContext;
5
+ msg: YuanbaoInboundMessage;
6
+ chatType: 'c2c' | 'group';
7
+ };
8
+ export type SystemCallbackHandler = (params: SystemCallbackParams) => void;
9
+ export declare function registerSystemCallback(command: string, handler: SystemCallbackHandler): void;
10
+ export declare function dispatchSystemCallback(params: SystemCallbackParams): boolean;
@@ -0,0 +1,17 @@
1
+ import { handleC2CRecall, handleGroupRecall } from './callbacks/recall.js';
2
+ const systemCallbackRegistry = new Map();
3
+ export function registerSystemCallback(command, handler) {
4
+ systemCallbackRegistry.set(command, handler);
5
+ }
6
+ export function dispatchSystemCallback(params) {
7
+ const command = params.msg.callback_command;
8
+ if (!command)
9
+ return false;
10
+ const handler = systemCallbackRegistry.get(command);
11
+ if (!handler)
12
+ return false;
13
+ handler(params);
14
+ return true;
15
+ }
16
+ registerSystemCallback('Group.CallbackAfterRecallMsg', ({ ctx, msg }) => handleGroupRecall(ctx, msg));
17
+ registerSystemCallback('C2C.CallbackAfterMsgWithDraw', ({ ctx, msg }) => handleC2CRecall(ctx, msg));
@@ -1,5 +1,5 @@
1
- import type { YuanbaoWsClient } from './yuanbao-server/ws/index.js';
2
- import { ResolvedYuanbaoAccount } from './types.js';
1
+ import type { YuanbaoWsClient } from '../yuanbao-server/ws/index.js';
2
+ import { ResolvedYuanbaoAccount } from '../types.js';
3
3
  import { OpenClawConfig } from 'openclaw/plugin-sdk';
4
4
  export interface ActionContext {
5
5
  wsClient: YuanbaoWsClient;
@@ -1,6 +1,6 @@
1
- import { searchStickers } from './sticker/sticker-cache.js';
2
- import { getOutboundQueue } from './outbound-queue.js';
3
- import { logger } from './logger.js';
1
+ import { searchStickers } from '../sticker/sticker-cache.js';
2
+ import { getOutboundQueue } from '../outbound-queue.js';
3
+ import { logger } from '../logger.js';
4
4
  function normalizeStickerSearchQuery(params) {
5
5
  const raw = params.query ?? params.keyword ?? params.q ?? params.text ?? params.search;
6
6
  if (typeof raw === 'string') {
@@ -0,0 +1 @@
1
+ export declare function buildMessageToolHints(): string[];
@@ -0,0 +1,6 @@
1
+ export function buildMessageToolHints() {
2
+ return [
3
+ 'file/image: real URLs/paths; send with media/mediaUrls, not link-only text.',
4
+ '表情=sticker=贴纸表情 (same). Use sticker-search + sticker; do not use Unicode emoji in text.',
5
+ ];
6
+ }
@@ -1 +1,2 @@
1
+ export { buildMessageToolHints } from './hints.js';
1
2
  export declare const yuanbaoMessageActions: Record<string, unknown>;
@@ -1,12 +1,12 @@
1
- import { getActiveWsClient } from './yuanbao-server/ws/index.js';
1
+ import { getActiveWsClient } from '../yuanbao-server/ws/index.js';
2
2
  import { handleYuanbaoAction } from './action-runtime.js';
3
- import { resolveYuanbaoAccount } from './accounts.js';
4
- import { handleAction as handleSendAction } from './dm/handle-action.js';
3
+ import { resolveYuanbaoAccount } from '../accounts.js';
4
+ import { handleAction as handleSendAction } from '../dm/handle-action.js';
5
+ export { buildMessageToolHints } from './hints.js';
5
6
  const SUPPORTED_ACTIONS = [
6
7
  'sticker-search',
7
8
  'sticker',
8
9
  'react',
9
- 'send',
10
10
  ];
11
11
  function describeMessageTool() {
12
12
  return {
@@ -74,6 +74,10 @@ export type YuanbaoMsgBodyElement = {
74
74
  [key: string]: unknown;
75
75
  };
76
76
  };
77
+ export type ImMsgSeq = {
78
+ msg_seq?: number;
79
+ msg_id?: string;
80
+ };
77
81
  export type YuanbaoInboundMessage = {
78
82
  callback_command?: string;
79
83
  from_account?: string;
@@ -93,6 +97,7 @@ export type YuanbaoInboundMessage = {
93
97
  cloud_custom_data?: string;
94
98
  event_time?: number;
95
99
  bot_owner_id?: string;
100
+ recall_msg_seq_list?: ImMsgSeq[];
96
101
  };
97
102
  export type QuoteInfo = {
98
103
  id?: string;
@@ -141,6 +141,7 @@ export function decodeInboundMessage(data) {
141
141
  cloud_custom_data: decoded.cloudCustomData || undefined,
142
142
  event_time: decoded.eventTime || undefined,
143
143
  bot_owner_id: decoded.botOwnerId || undefined,
144
+ recall_msg_seq_list: decoded.recall_msg_seq_list || undefined,
144
145
  };
145
146
  }
146
147
  export function decodeSendC2CMessageRsp(data, msgId) {
@@ -146,7 +146,12 @@ function parsePushContentToMsgBody(content) {
146
146
  return undefined;
147
147
  }
148
148
  function inferChatType(msg) {
149
- return (msg.group_code || msg.callback_command === 'Group.CallbackAfterSendMsg') ? 'group' : 'c2c';
149
+ if (msg.group_code)
150
+ return 'group';
151
+ const cmd = msg.callback_command;
152
+ if (cmd === 'Group.CallbackAfterRecallMsg' || cmd === 'Group.CallbackAfterSendMsg')
153
+ return 'group';
154
+ return 'c2c';
150
155
  }
151
156
  function hasValidMsgFields(msg) {
152
157
  return Boolean(msg.callback_command || msg.from_account || msg.msg_body);
@@ -11,6 +11,18 @@
11
11
  "nested": {
12
12
  "yuanbao_openclaw_proxy": {
13
13
  "nested": {
14
+ "ImMsgSeq": {
15
+ "fields": {
16
+ "msgSeq": {
17
+ "type": "uint64",
18
+ "id": 1
19
+ },
20
+ "msgId": {
21
+ "type": "string",
22
+ "id": 2
23
+ }
24
+ }
25
+ },
14
26
  "ImImageInfoArray": {
15
27
  "fields": {
16
28
  "type": {
@@ -244,6 +256,11 @@
244
256
  "botOwnerId": {
245
257
  "type": "string",
246
258
  "id": 15
259
+ },
260
+ "msgSeqList": {
261
+ "rule": "repeated",
262
+ "type": "ImMsgSeq",
263
+ "id": 16
247
264
  }
248
265
  }
249
266
  },
@@ -2,7 +2,7 @@
2
2
  "id": "openclaw-plugin-yuanbao",
3
3
  "name": "元宝 Bot",
4
4
  "description": "Tencent YuanBao intelligent bot channel plugin",
5
- "version": "2.0.0",
5
+ "version": "2.0.1",
6
6
  "channels": [
7
7
  "yuanbao"
8
8
  ],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openclaw-plugin-yuanbao",
3
- "version": "2.0.0",
3
+ "version": "2.0.1",
4
4
  "type": "module",
5
5
  "description": "Tencent YuanBao intelligent bot channel plugin",
6
6
  "license": "MIT",