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.
- package/dist/openclaw.plugin.json +1 -1
- package/dist/src/channel.js +15 -34
- package/dist/src/dm/handle-action.js +3 -1
- package/dist/src/message-handler/callbacks/recall.d.ts +4 -0
- package/dist/src/message-handler/callbacks/recall.js +90 -0
- package/dist/src/message-handler/chat-history.d.ts +19 -0
- package/dist/src/message-handler/chat-history.js +16 -0
- package/dist/src/message-handler/handlers/index.js +2 -15
- package/dist/src/message-handler/inbound.d.ts +1 -0
- package/dist/src/message-handler/inbound.js +5 -16
- package/dist/src/message-handler/index.d.ts +2 -0
- package/dist/src/message-handler/index.js +1 -0
- package/dist/src/message-handler/system-callbacks.d.ts +10 -0
- package/dist/src/message-handler/system-callbacks.js +17 -0
- package/dist/src/{action-runtime.d.ts → message-tool/action-runtime.d.ts} +2 -2
- package/dist/src/{action-runtime.js → message-tool/action-runtime.js} +3 -3
- package/dist/src/message-tool/hints.d.ts +1 -0
- package/dist/src/message-tool/hints.js +6 -0
- package/dist/src/{channel-actions.d.ts → message-tool/index.d.ts} +1 -0
- package/dist/src/{channel-actions.js → message-tool/index.js} +4 -4
- package/dist/src/types.d.ts +5 -0
- package/dist/src/yuanbao-server/ws/biz-codec.js +1 -0
- package/dist/src/yuanbao-server/ws/gateway.js +6 -1
- package/dist/src/yuanbao-server/ws/proto/biz.json +17 -0
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
package/dist/src/channel.js
CHANGED
|
@@ -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,
|
|
12
|
-
import { yuanbaoMessageActions } from './
|
|
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:
|
|
146
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
81
|
-
|
|
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
|
}
|
|
@@ -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
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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 '
|
|
2
|
-
import { ResolvedYuanbaoAccount } from '
|
|
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 '
|
|
2
|
-
import { getOutboundQueue } from '
|
|
3
|
-
import { logger } from '
|
|
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[];
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { getActiveWsClient } from '
|
|
1
|
+
import { getActiveWsClient } from '../yuanbao-server/ws/index.js';
|
|
2
2
|
import { handleYuanbaoAction } from './action-runtime.js';
|
|
3
|
-
import { resolveYuanbaoAccount } from '
|
|
4
|
-
import { handleAction as handleSendAction } from '
|
|
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 {
|
package/dist/src/types.d.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
},
|
package/openclaw.plugin.json
CHANGED