@qihoo/tuitui-openclaw-channel 1.0.46 → 1.0.47
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/package.json +1 -1
- package/dist/src/inbound.js +13 -12
- package/dist/src/inbound.js.map +1 -1
- package/package.json +1 -1
package/dist/package.json
CHANGED
package/dist/src/inbound.js
CHANGED
|
@@ -389,8 +389,8 @@ export async function handleInboundMessage({ json, account, apiRuntime, log }) {
|
|
|
389
389
|
const payload = {
|
|
390
390
|
chatType: CHAT_TYPE_DIRECT,
|
|
391
391
|
chatId: undefined,
|
|
392
|
-
botName: json.header['X-Tuitui-Robot-AppName'],
|
|
393
|
-
text:
|
|
392
|
+
botName: json.header['X-Tuitui-Robot-AppName'] || '',
|
|
393
|
+
text: "",
|
|
394
394
|
groupName: undefined,
|
|
395
395
|
WasMentioned: undefined,
|
|
396
396
|
channelName: undefined,
|
|
@@ -410,7 +410,6 @@ export async function handleInboundMessage({ json, account, apiRuntime, log }) {
|
|
|
410
410
|
}
|
|
411
411
|
if (!(await parseAndVerifyPayloadFun(payload, msgData, account, apiRuntime, log)))
|
|
412
412
|
return;
|
|
413
|
-
await injectSessionContext(payload, msgData, account);
|
|
414
413
|
if (!payload.chatId || !payload.msgId) {
|
|
415
414
|
log?.info?.(`[${CHANNEL_ID}] ignore unknown mseeage, missing chatId or msgId`, payload);
|
|
416
415
|
return;
|
|
@@ -429,22 +428,24 @@ export async function handleInboundMessage({ json, account, apiRuntime, log }) {
|
|
|
429
428
|
const cfg = await apiRuntime.config.loadConfig();
|
|
430
429
|
const sessionKey = getSessionKey(cfg, payload, account, apiRuntime);
|
|
431
430
|
log?.info?.(`[${CHANNEL_ID}] AccountId: ${accountId}, dispatching to agent session=${sessionKey}, chatType: ${payload.chatType}, chatId ${payload.chatId}, routeSenderFrom: ${routeSenderFrom}`);
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
431
|
+
payload.text = payload.text || '';
|
|
432
|
+
const stripedBody = payload.text.replace(`@${payload.botName}`, '').trim();
|
|
433
|
+
if (stripedBody.startsWith('/')) {
|
|
434
|
+
payload.text = stripedBody;
|
|
435
|
+
if (payload.text.startsWith('/new') || payload.text.startsWith('/reset')) {
|
|
436
|
+
// 清理agent上下文时,同时清空历史
|
|
437
|
+
popUnmentionedHistories(accountId, payload.chatId);
|
|
437
438
|
}
|
|
438
439
|
}
|
|
439
|
-
|
|
440
|
-
//
|
|
441
|
-
|
|
440
|
+
else {
|
|
441
|
+
// 指令以外的才注入
|
|
442
|
+
await injectSessionContext(payload, msgData, account);
|
|
442
443
|
}
|
|
443
444
|
// 字段意义 参考 openclaw 代码
|
|
444
445
|
// src\auto-reply\reply\inbound-meta.ts
|
|
445
446
|
// buildInboundUserContextPrefix()
|
|
446
447
|
const ctx = {
|
|
447
|
-
Body:
|
|
448
|
+
Body: payload.text,
|
|
448
449
|
From: String(routeSenderFrom),
|
|
449
450
|
To: CHANNEL_ID,
|
|
450
451
|
SessionId: sessionKey,
|
package/dist/src/inbound.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inbound.js","sourceRoot":"","sources":["../../src/inbound.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * TuiTui inbound message handler — pure business logic.\n *\n * channel.ts owns the WebSocket frame layer (JSON parse, ACK, keepalive\n * filtering) and calls handleInboundMessage with an already-parsed object.\n *\n * Usage:\n * ws.on('message', async (wsData) => {\n * // ... parse JSON, send ACK, filter keepalive ...\n * await handleInboundMessage(json, { account, accountId, apiRuntime, log });\n * });\n */\nimport type { TuiTuiInboundMessage, TuiTuiOutboundDeliverOptions } from './types';\nimport { CHANNEL_ID } from './const';\nimport {CHAT_TYPE_DIRECT,CHAT_TYPE_GROUP,CHAT_TYPE_CHANNEL,ChatType,teamsParseChatId,teamsBuildChatId} from \"./chat_base\"\nimport {tuituiEmojiReaction, sendTextMsg, sendPageMsg, sendMediaMsg } from \"./outbound\";\nimport { teams_get_members, teams_get_members_text, teams_get_announcement } from \"./teams_api\"\nimport { parseChatMessageBody } from './inbound_body_parse';\nimport { parseAllowFroms } from './utils';\nimport { addUnmentionedHistory, popUnmentionedHistories } from \"./histories\";\nimport { StringDeduplicator } from \"./deduplicator\"\nimport { getPostChainByChatId } from \"./chat_record\"\n\n// 会话上下文注入排重\nlet _session_ctx_injected = new StringDeduplicator(1000, 3600);\n\n/** 子函数共享的可变上下文,子函数直接修改字段,外层读取结果 */\ninterface ChatPayload {\n chatType: ChatType;\n chatId: string | undefined;\n botName: string;\n text: string | undefined;\n groupName: string | undefined;\n channelName: string | undefined;\n mediaUrls: string[] | undefined;\n replyToId: string | undefined; // 引用ID\n msgId?: string; // 消息ID\n tuituiAccount: string;\n tuituiUid: string | undefined;\n tuituiUserName: string | undefined;\n timestamp: Number | undefined;\n WasMentioned: boolean | undefined;\n}\n\nexport interface InboundAccount {\n accountId: string;\n appId: string;\n appSecret: string;\n dmPolicy: string;\n allowFrom: string[];\n groupPolicy: string;\n groupAllowFrom: string[];\n requireMention: boolean;\n emojiReaction: boolean;\n}\nexport interface InboundHandlerOptions {\n json: any\n account: InboundAccount;\n apiRuntime: any;\n log: any;\n}\n\nfunction getSessionKey(cfg: any, payload: ChatPayload, account: InboundAccount, apiRuntime: any): string {\n const { chatId, chatType } = payload;\n const { accountId } = account;\n // 你自己只需要拼接与定义 peer.id\n // 关于 sessionKey 格式的解释: https://docs.openclaw.ai/channels/channel-routing#sessionkey-%E5%8F%82%E8%80%83%E6%A0%BC%E5%BC%8F\n let id = chatId;\n if(chatType == CHAT_TYPE_CHANNEL) {\n const { channel_id, parent_id } = teamsParseChatId(chatId!);\n id = `${channel_id}`;\n if(parent_id) {\n id += `:thread:${parent_id}`;\n }\n }\n\n // sessionKey 不能自己拼字符串,需要用系统api识别,他会根据 bindings 路由规则处理\n const { sessionKey } = apiRuntime.channel.routing.resolveAgentRoute({\n cfg,\n accountId,\n channel: CHANNEL_ID,\n peer: { kind: chatType, id: id },\n });\n return String(sessionKey).replace(/\\//g, '_');\n}\n\nfunction getMediaUrls({ msg_type, images, voice, video, file }: any): string[] | undefined {\n if (msg_type === 'image' || msg_type === 'mixed') {\n if (images?.length) return images;\n } else if (msg_type === 'voice') {\n if (voice) return [voice];\n } else if (msg_type === 'video') {\n if (video) return [video];\n } else if (msg_type === 'file') {\n if (file?.url) return [file.url];\n }\n return undefined;\n}\n\nasync function dispatchReply(ctx: any, cfg: any, account: InboundAccount, payload: ChatPayload, apiRuntime: any, log: any) {\n const { accountId } = account;\n await apiRuntime.channel.reply.dispatchReplyWithBufferedBlockDispatcher({\n ctx,\n cfg,\n dispatcherOptions: {\n deliver: async (outbound: TuiTuiOutboundDeliverOptions) => {\n // Custom message (e.g. page)\n if (outbound.custom) {\n const { msgtype, page, tousers, togroups } = outbound.custom;\n if (msgtype === 'page' && page) {\n await sendPageMsg(account, payload.chatId, payload.chatType, page, 'tuitui.deliver.page', tousers, togroups);\n return;\n }\n log?.warn?.(`[${CHANNEL_ID}] AccountId: ${accountId}, Unsupported custom message type: ${msgtype}`);\n return;\n }\n\n // Media message\n const mediaUrl = outbound.mediaUrl || outbound.mediaUrls?.[0];\n if (mediaUrl) {\n await sendMediaMsg(account, payload.chatId, payload.chatType, mediaUrl, 'tuitui.deliver.media', [payload.tuituiAccount]);\n return;\n }\n\n // Text message\n const replyText = outbound?.text || outbound?.body;\n if (replyText) {\n // 群消息回复时不再使用 reference_msgid 避免并发时引用错乱,依靠 @ 来提醒用户\n await sendTextMsg(account, payload.chatId, payload.chatType, replyText, 'tuitui.deliver.text', [payload.tuituiAccount]);\n return;\n }\n log?.info?.(`[${CHANNEL_ID}] AccountId: ${accountId}, no_reply_content`);\n },\n\n onReplyStart: () => {\n log?.info?.(`[${CHANNEL_ID}] AccountId: ${accountId}, Agent is typing to ${payload.tuituiAccount}`);\n },\n },\n });\n}\n\n/*** 配对节流映射 - 用于防止短时间内大量重复配对请求消息发出\n * key: `${accountId}-${chatId}`\n * val: timestamp */\nconst pairingThrottleMap = new Map<string, number>();\n// 暂时控制为 2 分钟内同一个用户只能触发一次配对请求\nconst needPairingThrottle = (accountId: string | undefined, chatId: string, throttleMs = 2 * 60 * 1000): boolean => {\n const key = `${accountId}-${chatId}`;\n const now = Date.now();\n const lastTime = pairingThrottleMap.get(key) || 0;\n if (now - lastTime < throttleMs) {\n return true;\n }\n pairingThrottleMap.set(key, now);\n return false;\n}\n\nasync function sendSingleChatPairingMsg(account: any, payload: any, log: any, apiRuntime: any) {\n const { accountId } = account;\n const { chatId, chatType } = payload;\n if (needPairingThrottle(accountId, chatId)) {\n return log?.info?.(`[${CHANNEL_ID}] AccountId: ${accountId}, pairing throttled for sender=${chatId}`);\n }\n try {\n log?.debug?.(`[${CHANNEL_ID}] AccountId: ${accountId}, pairing flow: checking if pairing request exists for sender=${chatId}`);\n const req = await apiRuntime.channel.pairing.upsertPairingRequest({ channel: CHANNEL_ID, accountId, id: chatId });\n log?.debug?.(`[${CHANNEL_ID}] AccountId: ${accountId}, pairing flow: upsertPairingRequest result=${JSON.stringify(req)}`);\n // 只要没配对,会每次和机器人聊,都会返回配对信息。\n const replyText = apiRuntime.channel.pairing.buildPairingReply({ channel: CHANNEL_ID, code: req.code });\n await sendTextMsg(account, chatId, chatType, replyText, 'tuitui.pairing.reply');\n } catch (err) {\n log?.warn?.(`[${CHANNEL_ID}] AccountId: ${accountId}, pairing failed for ${chatId}: ${String(err)}`);\n }\n}\n\n//tuituiAccounts列表中是否存在至少1个允许私聊的用户(私聊白名单、配对、或者open)\nasync function isAllowOneOfAccount(tuituiAccounts: string[], apiRuntime: any, account: InboundAccount) {\n if(!tuituiAccounts) return false;\n const { accountId, allowFrom, dmPolicy } = account;\n if (dmPolicy === 'open') return true;\n\n // 是否包含任意一个元素\n if (tuituiAccounts.some(item => allowFrom.includes(item))) return true;\n\n try {\n let storeAllowFrom = parseAllowFroms(\n await apiRuntime?.channel?.pairing?.readAllowFromStore?.({ channel: CHANNEL_ID, accountId })\n );\n if (tuituiAccounts.some(item => storeAllowFrom.includes(item))) return true;\n } catch {}\n return false; \n}\n\nasync function isAllowAccount(tuituiAccount: string, apiRuntime: any, account: InboundAccount) {\n return await isAllowOneOfAccount([tuituiAccount], apiRuntime, account);\n}\n\nasync function isChannelCoordAuthorized(tuituiAccount: string, apiRuntime: any, account: InboundAccount, team_id:string, chat_id:string) {\n // 协调员身份校验\n if (tuituiAccount != \"bot-FiwwCeDw\" && tuituiAccount != \"bot-sUwUeknd\") return false;\n\n // 当前 thread 中有白名单用户发帖,则协调员继承该权限\n const [members, posts] = await Promise.all([\n teams_get_members(account, team_id),\n getPostChainByChatId(account, chat_id),\n ]);\n if (!members?.length || !posts?.length) return false;\n\n const from_uids = posts.map((p: any) => p.from_uid).filter(Boolean);\n if (!from_uids.length) return false;\n\n //console.log(\"from_uids\", from_uids);\n\n // 将 uid 映射到 user_account\n const from_accounts: string[] = members\n .filter((m: any) => from_uids.includes(m.uid) && m.account)\n .map((m: any) => String(m.account));\n if (!from_accounts.length) return false;\n\n //console.log(\"from_accounts\", from_accounts);\n return await isAllowOneOfAccount(from_accounts, apiRuntime, account);\n}\n\n\n/**\n * 处理单聊(single_chat)、群聊、团队帖子分支,直接修改并校验 payload。\n * 返回 false 表示消息不合法,外层应提前 return;返回 true 表示校验通过,继续执行。\n */\nasync function parse_single_chat(payload: ChatPayload, msgData: any, account: InboundAccount, apiRuntime: any, log: any): Promise<boolean> {\n const { accountId, dmPolicy, allowFrom } = account;\n const chatId = payload.tuituiAccount ? String(payload.tuituiAccount || '').toLowerCase().trim() : '';\n if (dmPolicy === 'disabled') { //['pairing', 'allowlist', 'open', 'disabled'],\n log?.warn?.(`[${CHANNEL_ID}] AccountId: ${accountId}, DM disabled sender=${chatId}`);\n return false;\n }\n\n payload.chatType = CHAT_TYPE_DIRECT;\n payload.chatId = chatId;\n payload.text = parseChatMessageBody(msgData);\n payload.msgId = msgData.msgid;\n log?.debug?.(\n `[${CHANNEL_ID}] AccountId: ${accountId}, inbound single_chat:\n userAccount=${chatId},\n tuituiUid=${payload.tuituiUid},\n tuituiUserName=${payload.tuituiUserName},\n dmPolicy=${dmPolicy},\n allowFrom=${JSON.stringify(allowFrom)}`);\n\n if (!chatId && !payload.tuituiUid) {\n log?.info?.(`[${CHANNEL_ID}] AccountId: ${accountId}, Missing user_account or uid in single_chat event`);\n return false;\n }\n\n if (dmPolicy === 'open') return true;\n\n if(await isAllowAccount(chatId, apiRuntime, account)){\n return true;\n }\n\n if (dmPolicy === 'pairing') {\n sendSingleChatPairingMsg(account, payload, log, apiRuntime);\n log?.info?.(`[${CHANNEL_ID}] AccountId: ${accountId}, pairing required`);\n return false;\n }\n // allowlist\n log?.warn?.(`[${CHANNEL_ID}] AccountId: ${accountId}, Blocked unauthorized sender (allowlist): sender=${chatId} allowFrom=${JSON.stringify(allowFrom)}`);\n return false;\n}\n\nasync function parse_group_chat(payload: ChatPayload, msgData: any, account: InboundAccount, apiRuntime: any, log: any): Promise<boolean> {\n const { accountId, groupPolicy, groupAllowFrom } = account;\n payload.chatType = CHAT_TYPE_GROUP;\n const chatId = msgData.group_id ? String(msgData.group_id).toLowerCase().trim() : '';\n payload.chatId = chatId;\n payload.groupName = msgData.group_name;\n payload.msgId = msgData.msgid;\n payload.text = parseChatMessageBody(msgData);\n payload.WasMentioned = msgData.at_me;\n const { tuituiAccount } = payload;\n log?.debug?.(\n `[${CHANNEL_ID}] AccountId: ${accountId}, inbound group_chat:\n tuituiAccount=${tuituiAccount},\n tuituiUid=${payload.tuituiUid},\n tuituiUserName=${payload.tuituiUserName},\n groupId=${chatId},\n groupPolicy=${groupPolicy},\n groupAllowFrom=${JSON.stringify(groupAllowFrom)},\n at_me=${JSON.stringify(msgData.at_me)},\n at=${JSON.stringify(msgData.at)}`);\n\n if (groupPolicy === 'disabled') {\n log?.info?.(`${CHANNEL_ID} AccountId: ${accountId}, groupPolicy disabled`);\n return false;\n }\n\n if (!tuituiAccount || !chatId) {\n log?.info?.(`[${CHANNEL_ID}] AccountId: ${accountId}, Missing tuituiAccount or chatId in group_chat event`);\n return false;\n }\n\n if (!msgData.at_me && account.requireMention) {\n log?.info?.(`[${CHANNEL_ID}] AccountId: ${accountId}, ignore group message (not mentioned), add to history key: ${chatId}`);\n await addUnmentionedHistory(apiRuntime, accountId, chatId, payload.tuituiUserName, tuituiAccount, payload.text, payload.timestamp);\n return false;\n }\n\n // 私聊白名单对群聊仍然生效,当群里只想特定人@时,可以不配置groupAllowFrom,而是配置 allowFrom\n if(await isAllowAccount(tuituiAccount, apiRuntime, account)){\n return true;\n }\n\n if (!groupAllowFrom.includes(chatId)) {\n if (needPairingThrottle(accountId, chatId)) {\n log?.info?.(`[${CHANNEL_ID}] AccountId: ${accountId}, group pairing throttled for groupId=${chatId}`);\n return false;\n }\n\n const msgTxt=`当前 OpenClaw(AccountId: ${accountId})的群聊策略为白名单模式。\n需由龙虾主人在配置中添加白名单(两种方式二选一即可):\n\n- 允许群中所有人用,在群白名单(Group Allow From)添加当前群ID: ${chatId}\n\n- 不想群所有人用,只想特定人用,在私聊白名单(Allow From)添加当前用户 ${payload.tuituiAccount} ,私聊白名单对群仍然有效`\n\n await sendTextMsg(account, chatId, payload.chatType, msgTxt, 'tuitui.groupPolicy.reply');\n return false;\n }\n\n return true; \n}\n\n\nasync function parse_teams_post(payload: ChatPayload, msgData: any, account: InboundAccount, apiRuntime: any, log: any): Promise<boolean> {\n const { accountId, groupPolicy, groupAllowFrom } = account;\n payload.chatType = CHAT_TYPE_CHANNEL;\n const { team_id, channel_id, parent_id, post_id, content, team_name, channel_name } = msgData;\n const thread_id = (parent_id && parent_id != \"0\")?parent_id: post_id;\n const chatId = teamsBuildChatId(team_id, channel_id, thread_id);\n payload.chatId = chatId;\n payload.msgId = post_id;\n payload.text = content;\n payload.channelName = channel_name;\n payload.replyToId = \"\";\n payload.WasMentioned = msgData.at_me;\n const { tuituiAccount } = payload;\n log?.debug?.(\n `[${CHANNEL_ID}] AccountId: ${accountId}, inbound teams:\n tuituiAccount=${tuituiAccount},\n tuituiUid=${payload.tuituiUid},\n tuituiUserName=${payload.tuituiUserName},\n chatId=${chatId},\n groupPolicy=${groupPolicy},\n groupAllowFrom=${JSON.stringify(groupAllowFrom)},\n at_me=${JSON.stringify(msgData.at_me)},\n at=${JSON.stringify(msgData.at)}`,\n );\n\n if (groupPolicy === 'disabled') {\n log?.info?.(`${CHANNEL_ID} AccountId: ${accountId}, groupPolicy disabled`);\n return false;\n }\n\n if (!tuituiAccount) {\n log?.info?.(`[${CHANNEL_ID}] AccountId: ${accountId}, Missing tuituiAccount or chatId in event`);\n return false;\n }\n\n \n {\n // 频道帖子文件、附件处理。必须放在正文里\n const {images, files} = msgData;\n if (images) {\n payload.text += \"\\n\\n附录上文提到的图片列表\\n\"\n for (const image of images) {\n payload.text += image + \"\\n\";\n }\n }\n if (files) {\n payload.text += \"\\n\\n附录上文提到的文件列表\\n\"\n for (const file of files) {\n payload.text += `[文件] ${file?.name} : ${file?.url} \\n`;\n }\n }\n }\n\n if (!msgData.at_me && account.requireMention) {\n log?.info?.(`[${CHANNEL_ID}] AccountId: ${accountId}, ignore teams post (not mentioned), add to history ${chatId} -> ${payload.text}`);\n await addUnmentionedHistory(apiRuntime, accountId, chatId, payload.tuituiUserName, tuituiAccount, payload.text, payload.timestamp);\n return false;\n }\n\n // 私聊白名单对团队仍然生效,限制特定人@时,可以不配置groupAllowFrom,而是配置 allowFrom\n if(await isAllowAccount(tuituiAccount, apiRuntime, account)){\n return true;\n }\n \n if (!groupAllowFrom.includes(String(team_id)) && !groupAllowFrom.includes(String(channel_id)) ) {\n if (!msgData.at_me) {\n // 解决这个case:requireMention=false时,团队里发任意帖子都会回复加白,搞得没法用\n // 要求必须@才触发回复加白\n log?.info?.(`[${CHANNEL_ID}] AccountId: ${accountId}, ignore teams post (not mentioned)`);\n return false;\n }\n\n // 频道中允许协调员@自己(且帖子里有白名单用户发帖)\n if (await isChannelCoordAuthorized(tuituiAccount, apiRuntime, account, team_id, chatId)) {\n return true;\n }\n\n if (needPairingThrottle(accountId, chatId)) {\n log?.info?.(`[${CHANNEL_ID}] AccountId: ${accountId}, teams pairing throttled for teamsChatId=${chatId}`);\n return false;\n }\n\n const msgTxt=`当前 OpenClaw(AccountId: ${accountId})的群聊/团队策略为白名单模式。\n需由龙虾主人在配置中添加白名单(3种方式选一种即可):\n\n- 允许团队中所有人用,在群白名单(Group Allow From)添加当前团队ID: ${team_id}\n- 仅允许当前频道使用,在群白名单(Group Allow From)添加当前频道ID: ${channel_id}\n- 仅允许特定人使用,在私聊白名单(Allow From)添加当前用户: ${payload.tuituiAccount} ,私聊白名单对团队仍然有效`\n\n await sendTextMsg(account, chatId, payload.chatType, msgTxt, 'tuitui.groupPolicy.reply');\n return false;\n }\n\n return true;\n}\n\nconst parseAndVerifyPayload: Record<string, Function> = {\n single_chat: parse_single_chat,\n group_chat: parse_group_chat,\n teams_post_create: parse_teams_post,\n //teams_post_modify: parse_teams_post,\n} as const;\n\nasync function injectSessionContext(payload: ChatPayload, msgData: any, account: InboundAccount) {\n const { accountId } = account;\n if(!_session_ctx_injected.checkAndRecord(accountId + \"_\" + payload.chatId)) return;\n // 注入上下文\n\n if (payload.chatType === CHAT_TYPE_CHANNEL) {\n // 解决机器人不知道自己是谁的问题 (仅团队有效)\n if(payload.botName) {\n payload.text += `\\n\\n*** 参考信息: 你在当前session中的名字叫: ${payload.botName} 如果有人@这个名字,就是在命令你 ***\\n`;\n }\n\n const { team_id, channel_id } = msgData;\n // 公告\n const annnouncement = await teams_get_announcement(account, channel_id, false);\n if(annnouncement) {\n payload.text += \"\\n\\n*** 参考信息: 当前公告内容如下 ***\\n\";\n payload.text += \"```\\n\" + annnouncement + \"\\n```\";\n }\n\n // 成员\n const members = await teams_get_members_text(account, team_id);\n if(members) {\n payload.text += \"\\n\\n*** 参考信息: 当前团队成员清单如下,每行一个成员名。如果需要询问成员、或者发送给成员时,需要用 @名字 的语法;并且@时必须从如下清单中匹配到最接近的,禁止@不存在的成员 ***\\n\";\n payload.text += \"```\\n\" + members + \"\\n```\";\n }\n }\n\n payload.text += `\\n\\n【关键系统指令:产物交付】\\n如果你的最终任务目标是生成文件(pdf/图片/Markdown/等),在文件生成落盘后你当前的任务并没有结束!你必须使用 \\`message\\` tool 将这些文件二进制作为 attachments 发回到当前 session 中`;\n}\n\n/**\n * 处理长链接消息\n * account: 长连接初始化时,对应的Account配置信息\n * accountId: 长连接启动初始化,对应的配置ID\n */\nexport async function handleInboundMessage({ json, account, apiRuntime, log }: InboundHandlerOptions) {\n // Signature / AppId validation\n const { accountId, appId, appSecret } = account;\n if (appSecret && appId && json.header['X-Tuitui-Robot-Appid'] !== appId) {\n log?.info?.(`[${CHANNEL_ID}] Invalid appId`);\n return;\n }\n\n // Decode message\n const msg = json.body as TuiTuiInboundMessage;\n const msgData = msg.data;\n const { ref } = msgData;\n const payload: ChatPayload = {\n chatType: CHAT_TYPE_DIRECT,\n chatId: undefined, \n botName: json.header['X-Tuitui-Robot-AppName'],\n text: undefined,\n groupName: undefined,\n WasMentioned: undefined,\n channelName: undefined,\n mediaUrls: getMediaUrls(msgData),\n replyToId: ref?.is_me && ref?.msgid ? ref.msgid : undefined,\n tuituiAccount: msg.user_account || \"\",\n tuituiUid: msg.uid || \"\",\n tuituiUserName: msg.user_name || \"\",\n timestamp: msg.timestamp ? parseInt(msg.timestamp, 10)*1000 : undefined\n };\n const wsEvent = json.body.event;\n // 按event类型,标准化并校验基础数据\n const parseAndVerifyPayloadFun = parseAndVerifyPayload[wsEvent] as Function | undefined;\n if (!parseAndVerifyPayloadFun) {\n log?.info?.(`[${CHANNEL_ID}] ignore unknown event ${wsEvent}`);\n return;\n }\n if (!(await parseAndVerifyPayloadFun(payload, msgData, account, apiRuntime, log))) return;\n\n await injectSessionContext(payload, msgData, account);\n\n if (!payload.chatId || !payload.msgId) {\n log?.info?.(`[${CHANNEL_ID}] ignore unknown mseeage, missing chatId or msgId`, payload);\n return;\n }\n\n if (account.emojiReaction) {\n // 因为回复较慢,先回复一个表情\n try{\n await tuituiEmojiReaction(account, payload.chatId, payload.chatType, payload.msgId, '收到');\n } catch (err) {\n // 出错不影响后续逻辑\n }\n }\n\n // 路由判断\n const routeSenderFrom = payload.tuituiAccount || payload.tuituiUid || 'unknown';\n\n const cfg = await apiRuntime.config.loadConfig();\n const sessionKey = getSessionKey(cfg, payload, account, apiRuntime);\n log?.info?.(`[${CHANNEL_ID}] AccountId: ${accountId}, dispatching to agent session=${sessionKey}, chatType: ${payload.chatType}, chatId ${payload.chatId}, routeSenderFrom: ${routeSenderFrom}`);\n\n let finalBody = payload.text || ' ';\n if (payload.text && payload.botName) {\n const stripped = payload.text.replace(`@${payload.botName}`, '').trim();\n if (stripped.startsWith('/')) {\n finalBody = stripped;\n }\n }\n\n if(finalBody.startsWith(\"/new\") || finalBody.endsWith(\"/new\")) {\n // 清理agent上下文时,同时清空历史\n popUnmentionedHistories(accountId, payload.chatId);\n }\n\n // 字段意义 参考 openclaw 代码\n // src\\auto-reply\\reply\\inbound-meta.ts\n // buildInboundUserContextPrefix()\n const ctx: any = {\n Body: finalBody,\n From: String(routeSenderFrom),\n To: CHANNEL_ID,\n SessionId: sessionKey,\n SessionKey: sessionKey,\n AccountId: accountId,\n OriginatingChannel: CHANNEL_ID,\n OriginatingTo: payload.chatId,\n ChatType: payload.chatType!,\n Surface: CHANNEL_ID,\n Provider: CHANNEL_ID,\n SenderName: payload.tuituiUserName,\n SenderId: payload.tuituiAccount,\n SenderUsername: payload.tuituiAccount, \n UserAccount: payload.tuituiAccount,\n Timestamp: payload.timestamp,\n CommandAuthorized: true, // 允许 /new 等内置命令\n };\n if (payload.chatType == CHAT_TYPE_GROUP && payload.chatId) {\n ctx.WasMentioned = payload.WasMentioned;\n ctx.GroupSubject = payload.groupName;\n ctx.GroupId = payload.chatId;\n ctx.InboundHistory = popUnmentionedHistories(accountId, payload.chatId);\n }\n if (payload.chatType == CHAT_TYPE_CHANNEL) {\n ctx.WasMentioned = payload.WasMentioned;\n ctx.IsForum = true;\n ctx.GroupSubject = payload.channelName;\n ctx.GroupChannel = payload.chatId;\n ctx.InboundHistory = popUnmentionedHistories(accountId, payload.chatId);\n }\n if (payload.mediaUrls?.length) ctx.MediaUrls = payload.mediaUrls;\n if (payload.replyToId) ctx.ReplyToId = payload.replyToId;\n\n log?.info?.(`[${CHANNEL_ID}] AccountId: ${accountId}, handleInboundMessage dispatchReply ctx: ${JSON.stringify(ctx, null, ' ')}`);\n try {\n await dispatchReply(ctx, cfg, account, payload, apiRuntime, log);\n } catch (err) {\n log?.error?.(`[${CHANNEL_ID}] AccountId: ${accountId}, dispatchReply failed:`, err);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"inbound.js","sourceRoot":"","sources":["../../src/inbound.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * TuiTui inbound message handler — pure business logic.\n *\n * channel.ts owns the WebSocket frame layer (JSON parse, ACK, keepalive\n * filtering) and calls handleInboundMessage with an already-parsed object.\n *\n * Usage:\n * ws.on('message', async (wsData) => {\n * // ... parse JSON, send ACK, filter keepalive ...\n * await handleInboundMessage(json, { account, accountId, apiRuntime, log });\n * });\n */\nimport type { TuiTuiInboundMessage, TuiTuiOutboundDeliverOptions } from './types';\nimport { CHANNEL_ID } from './const';\nimport {CHAT_TYPE_DIRECT,CHAT_TYPE_GROUP,CHAT_TYPE_CHANNEL,ChatType,teamsParseChatId,teamsBuildChatId} from \"./chat_base\"\nimport {tuituiEmojiReaction, sendTextMsg, sendPageMsg, sendMediaMsg } from \"./outbound\";\nimport { teams_get_members, teams_get_members_text, teams_get_announcement } from \"./teams_api\"\nimport { parseChatMessageBody } from './inbound_body_parse';\nimport { parseAllowFroms } from './utils';\nimport { addUnmentionedHistory, popUnmentionedHistories } from \"./histories\";\nimport { StringDeduplicator } from \"./deduplicator\"\nimport { getPostChainByChatId } from \"./chat_record\"\n\n// 会话上下文注入排重\nlet _session_ctx_injected = new StringDeduplicator(1000, 3600);\n\n/** 子函数共享的可变上下文,子函数直接修改字段,外层读取结果 */\ninterface ChatPayload {\n chatType: ChatType;\n chatId: string | undefined;\n botName: string;\n text: string | undefined;\n groupName: string | undefined;\n channelName: string | undefined;\n mediaUrls: string[] | undefined;\n replyToId: string | undefined; // 引用ID\n msgId?: string; // 消息ID\n tuituiAccount: string;\n tuituiUid: string | undefined;\n tuituiUserName: string | undefined;\n timestamp: Number | undefined;\n WasMentioned: boolean | undefined;\n}\n\nexport interface InboundAccount {\n accountId: string;\n appId: string;\n appSecret: string;\n dmPolicy: string;\n allowFrom: string[];\n groupPolicy: string;\n groupAllowFrom: string[];\n requireMention: boolean;\n emojiReaction: boolean;\n}\nexport interface InboundHandlerOptions {\n json: any\n account: InboundAccount;\n apiRuntime: any;\n log: any;\n}\n\nfunction getSessionKey(cfg: any, payload: ChatPayload, account: InboundAccount, apiRuntime: any): string {\n const { chatId, chatType } = payload;\n const { accountId } = account;\n // 你自己只需要拼接与定义 peer.id\n // 关于 sessionKey 格式的解释: https://docs.openclaw.ai/channels/channel-routing#sessionkey-%E5%8F%82%E8%80%83%E6%A0%BC%E5%BC%8F\n let id = chatId;\n if(chatType == CHAT_TYPE_CHANNEL) {\n const { channel_id, parent_id } = teamsParseChatId(chatId!);\n id = `${channel_id}`;\n if(parent_id) {\n id += `:thread:${parent_id}`;\n }\n }\n\n // sessionKey 不能自己拼字符串,需要用系统api识别,他会根据 bindings 路由规则处理\n const { sessionKey } = apiRuntime.channel.routing.resolveAgentRoute({\n cfg,\n accountId,\n channel: CHANNEL_ID,\n peer: { kind: chatType, id: id },\n });\n return String(sessionKey).replace(/\\//g, '_');\n}\n\nfunction getMediaUrls({ msg_type, images, voice, video, file }: any): string[] | undefined {\n if (msg_type === 'image' || msg_type === 'mixed') {\n if (images?.length) return images;\n } else if (msg_type === 'voice') {\n if (voice) return [voice];\n } else if (msg_type === 'video') {\n if (video) return [video];\n } else if (msg_type === 'file') {\n if (file?.url) return [file.url];\n }\n return undefined;\n}\n\nasync function dispatchReply(ctx: any, cfg: any, account: InboundAccount, payload: ChatPayload, apiRuntime: any, log: any) {\n const { accountId } = account;\n await apiRuntime.channel.reply.dispatchReplyWithBufferedBlockDispatcher({\n ctx,\n cfg,\n dispatcherOptions: {\n deliver: async (outbound: TuiTuiOutboundDeliverOptions) => {\n // Custom message (e.g. page)\n if (outbound.custom) {\n const { msgtype, page, tousers, togroups } = outbound.custom;\n if (msgtype === 'page' && page) {\n await sendPageMsg(account, payload.chatId, payload.chatType, page, 'tuitui.deliver.page', tousers, togroups);\n return;\n }\n log?.warn?.(`[${CHANNEL_ID}] AccountId: ${accountId}, Unsupported custom message type: ${msgtype}`);\n return;\n }\n\n // Media message\n const mediaUrl = outbound.mediaUrl || outbound.mediaUrls?.[0];\n if (mediaUrl) {\n await sendMediaMsg(account, payload.chatId, payload.chatType, mediaUrl, 'tuitui.deliver.media', [payload.tuituiAccount]);\n return;\n }\n\n // Text message\n const replyText = outbound?.text || outbound?.body;\n if (replyText) {\n // 群消息回复时不再使用 reference_msgid 避免并发时引用错乱,依靠 @ 来提醒用户\n await sendTextMsg(account, payload.chatId, payload.chatType, replyText, 'tuitui.deliver.text', [payload.tuituiAccount]);\n return;\n }\n log?.info?.(`[${CHANNEL_ID}] AccountId: ${accountId}, no_reply_content`);\n },\n\n onReplyStart: () => {\n log?.info?.(`[${CHANNEL_ID}] AccountId: ${accountId}, Agent is typing to ${payload.tuituiAccount}`);\n },\n },\n });\n}\n\n/*** 配对节流映射 - 用于防止短时间内大量重复配对请求消息发出\n * key: `${accountId}-${chatId}`\n * val: timestamp */\nconst pairingThrottleMap = new Map<string, number>();\n// 暂时控制为 2 分钟内同一个用户只能触发一次配对请求\nconst needPairingThrottle = (accountId: string | undefined, chatId: string, throttleMs = 2 * 60 * 1000): boolean => {\n const key = `${accountId}-${chatId}`;\n const now = Date.now();\n const lastTime = pairingThrottleMap.get(key) || 0;\n if (now - lastTime < throttleMs) {\n return true;\n }\n pairingThrottleMap.set(key, now);\n return false;\n}\n\nasync function sendSingleChatPairingMsg(account: any, payload: any, log: any, apiRuntime: any) {\n const { accountId } = account;\n const { chatId, chatType } = payload;\n if (needPairingThrottle(accountId, chatId)) {\n return log?.info?.(`[${CHANNEL_ID}] AccountId: ${accountId}, pairing throttled for sender=${chatId}`);\n }\n try {\n log?.debug?.(`[${CHANNEL_ID}] AccountId: ${accountId}, pairing flow: checking if pairing request exists for sender=${chatId}`);\n const req = await apiRuntime.channel.pairing.upsertPairingRequest({ channel: CHANNEL_ID, accountId, id: chatId });\n log?.debug?.(`[${CHANNEL_ID}] AccountId: ${accountId}, pairing flow: upsertPairingRequest result=${JSON.stringify(req)}`);\n // 只要没配对,会每次和机器人聊,都会返回配对信息。\n const replyText = apiRuntime.channel.pairing.buildPairingReply({ channel: CHANNEL_ID, code: req.code });\n await sendTextMsg(account, chatId, chatType, replyText, 'tuitui.pairing.reply');\n } catch (err) {\n log?.warn?.(`[${CHANNEL_ID}] AccountId: ${accountId}, pairing failed for ${chatId}: ${String(err)}`);\n }\n}\n\n//tuituiAccounts列表中是否存在至少1个允许私聊的用户(私聊白名单、配对、或者open)\nasync function isAllowOneOfAccount(tuituiAccounts: string[], apiRuntime: any, account: InboundAccount) {\n if(!tuituiAccounts) return false;\n const { accountId, allowFrom, dmPolicy } = account;\n if (dmPolicy === 'open') return true;\n\n // 是否包含任意一个元素\n if (tuituiAccounts.some(item => allowFrom.includes(item))) return true;\n\n try {\n let storeAllowFrom = parseAllowFroms(\n await apiRuntime?.channel?.pairing?.readAllowFromStore?.({ channel: CHANNEL_ID, accountId })\n );\n if (tuituiAccounts.some(item => storeAllowFrom.includes(item))) return true;\n } catch {}\n return false; \n}\n\nasync function isAllowAccount(tuituiAccount: string, apiRuntime: any, account: InboundAccount) {\n return await isAllowOneOfAccount([tuituiAccount], apiRuntime, account);\n}\n\nasync function isChannelCoordAuthorized(tuituiAccount: string, apiRuntime: any, account: InboundAccount, team_id:string, chat_id:string) {\n // 协调员身份校验\n if (tuituiAccount != \"bot-FiwwCeDw\" && tuituiAccount != \"bot-sUwUeknd\") return false;\n\n // 当前 thread 中有白名单用户发帖,则协调员继承该权限\n const [members, posts] = await Promise.all([\n teams_get_members(account, team_id),\n getPostChainByChatId(account, chat_id),\n ]);\n if (!members?.length || !posts?.length) return false;\n\n const from_uids = posts.map((p: any) => p.from_uid).filter(Boolean);\n if (!from_uids.length) return false;\n\n //console.log(\"from_uids\", from_uids);\n\n // 将 uid 映射到 user_account\n const from_accounts: string[] = members\n .filter((m: any) => from_uids.includes(m.uid) && m.account)\n .map((m: any) => String(m.account));\n if (!from_accounts.length) return false;\n\n //console.log(\"from_accounts\", from_accounts);\n return await isAllowOneOfAccount(from_accounts, apiRuntime, account);\n}\n\n\n/**\n * 处理单聊(single_chat)、群聊、团队帖子分支,直接修改并校验 payload。\n * 返回 false 表示消息不合法,外层应提前 return;返回 true 表示校验通过,继续执行。\n */\nasync function parse_single_chat(payload: ChatPayload, msgData: any, account: InboundAccount, apiRuntime: any, log: any): Promise<boolean> {\n const { accountId, dmPolicy, allowFrom } = account;\n const chatId = payload.tuituiAccount ? String(payload.tuituiAccount || '').toLowerCase().trim() : '';\n if (dmPolicy === 'disabled') { //['pairing', 'allowlist', 'open', 'disabled'],\n log?.warn?.(`[${CHANNEL_ID}] AccountId: ${accountId}, DM disabled sender=${chatId}`);\n return false;\n }\n\n payload.chatType = CHAT_TYPE_DIRECT;\n payload.chatId = chatId;\n payload.text = parseChatMessageBody(msgData);\n payload.msgId = msgData.msgid;\n log?.debug?.(\n `[${CHANNEL_ID}] AccountId: ${accountId}, inbound single_chat:\n userAccount=${chatId},\n tuituiUid=${payload.tuituiUid},\n tuituiUserName=${payload.tuituiUserName},\n dmPolicy=${dmPolicy},\n allowFrom=${JSON.stringify(allowFrom)}`);\n\n if (!chatId && !payload.tuituiUid) {\n log?.info?.(`[${CHANNEL_ID}] AccountId: ${accountId}, Missing user_account or uid in single_chat event`);\n return false;\n }\n\n if (dmPolicy === 'open') return true;\n\n if(await isAllowAccount(chatId, apiRuntime, account)){\n return true;\n }\n\n if (dmPolicy === 'pairing') {\n sendSingleChatPairingMsg(account, payload, log, apiRuntime);\n log?.info?.(`[${CHANNEL_ID}] AccountId: ${accountId}, pairing required`);\n return false;\n }\n // allowlist\n log?.warn?.(`[${CHANNEL_ID}] AccountId: ${accountId}, Blocked unauthorized sender (allowlist): sender=${chatId} allowFrom=${JSON.stringify(allowFrom)}`);\n return false;\n}\n\nasync function parse_group_chat(payload: ChatPayload, msgData: any, account: InboundAccount, apiRuntime: any, log: any): Promise<boolean> {\n const { accountId, groupPolicy, groupAllowFrom } = account;\n payload.chatType = CHAT_TYPE_GROUP;\n const chatId = msgData.group_id ? String(msgData.group_id).toLowerCase().trim() : '';\n payload.chatId = chatId;\n payload.groupName = msgData.group_name;\n payload.msgId = msgData.msgid;\n payload.text = parseChatMessageBody(msgData);\n payload.WasMentioned = msgData.at_me;\n const { tuituiAccount } = payload;\n log?.debug?.(\n `[${CHANNEL_ID}] AccountId: ${accountId}, inbound group_chat:\n tuituiAccount=${tuituiAccount},\n tuituiUid=${payload.tuituiUid},\n tuituiUserName=${payload.tuituiUserName},\n groupId=${chatId},\n groupPolicy=${groupPolicy},\n groupAllowFrom=${JSON.stringify(groupAllowFrom)},\n at_me=${JSON.stringify(msgData.at_me)},\n at=${JSON.stringify(msgData.at)}`);\n\n if (groupPolicy === 'disabled') {\n log?.info?.(`${CHANNEL_ID} AccountId: ${accountId}, groupPolicy disabled`);\n return false;\n }\n\n if (!tuituiAccount || !chatId) {\n log?.info?.(`[${CHANNEL_ID}] AccountId: ${accountId}, Missing tuituiAccount or chatId in group_chat event`);\n return false;\n }\n\n if (!msgData.at_me && account.requireMention) {\n log?.info?.(`[${CHANNEL_ID}] AccountId: ${accountId}, ignore group message (not mentioned), add to history key: ${chatId}`);\n await addUnmentionedHistory(apiRuntime, accountId, chatId, payload.tuituiUserName, tuituiAccount, payload.text, payload.timestamp);\n return false;\n }\n\n // 私聊白名单对群聊仍然生效,当群里只想特定人@时,可以不配置groupAllowFrom,而是配置 allowFrom\n if(await isAllowAccount(tuituiAccount, apiRuntime, account)){\n return true;\n }\n\n if (!groupAllowFrom.includes(chatId)) {\n if (needPairingThrottle(accountId, chatId)) {\n log?.info?.(`[${CHANNEL_ID}] AccountId: ${accountId}, group pairing throttled for groupId=${chatId}`);\n return false;\n }\n\n const msgTxt=`当前 OpenClaw(AccountId: ${accountId})的群聊策略为白名单模式。\n需由龙虾主人在配置中添加白名单(两种方式二选一即可):\n\n- 允许群中所有人用,在群白名单(Group Allow From)添加当前群ID: ${chatId}\n\n- 不想群所有人用,只想特定人用,在私聊白名单(Allow From)添加当前用户 ${payload.tuituiAccount} ,私聊白名单对群仍然有效`\n\n await sendTextMsg(account, chatId, payload.chatType, msgTxt, 'tuitui.groupPolicy.reply');\n return false;\n }\n\n return true; \n}\n\n\nasync function parse_teams_post(payload: ChatPayload, msgData: any, account: InboundAccount, apiRuntime: any, log: any): Promise<boolean> {\n const { accountId, groupPolicy, groupAllowFrom } = account;\n payload.chatType = CHAT_TYPE_CHANNEL;\n const { team_id, channel_id, parent_id, post_id, content, team_name, channel_name } = msgData;\n const thread_id = (parent_id && parent_id != \"0\")?parent_id: post_id;\n const chatId = teamsBuildChatId(team_id, channel_id, thread_id);\n payload.chatId = chatId;\n payload.msgId = post_id;\n payload.text = content;\n payload.channelName = channel_name;\n payload.replyToId = \"\";\n payload.WasMentioned = msgData.at_me;\n const { tuituiAccount } = payload;\n log?.debug?.(\n `[${CHANNEL_ID}] AccountId: ${accountId}, inbound teams:\n tuituiAccount=${tuituiAccount},\n tuituiUid=${payload.tuituiUid},\n tuituiUserName=${payload.tuituiUserName},\n chatId=${chatId},\n groupPolicy=${groupPolicy},\n groupAllowFrom=${JSON.stringify(groupAllowFrom)},\n at_me=${JSON.stringify(msgData.at_me)},\n at=${JSON.stringify(msgData.at)}`,\n );\n\n if (groupPolicy === 'disabled') {\n log?.info?.(`${CHANNEL_ID} AccountId: ${accountId}, groupPolicy disabled`);\n return false;\n }\n\n if (!tuituiAccount) {\n log?.info?.(`[${CHANNEL_ID}] AccountId: ${accountId}, Missing tuituiAccount or chatId in event`);\n return false;\n }\n\n \n {\n // 频道帖子文件、附件处理。必须放在正文里\n const {images, files} = msgData;\n if (images) {\n payload.text += \"\\n\\n附录上文提到的图片列表\\n\"\n for (const image of images) {\n payload.text += image + \"\\n\";\n }\n }\n if (files) {\n payload.text += \"\\n\\n附录上文提到的文件列表\\n\"\n for (const file of files) {\n payload.text += `[文件] ${file?.name} : ${file?.url} \\n`;\n }\n }\n }\n\n if (!msgData.at_me && account.requireMention) {\n log?.info?.(`[${CHANNEL_ID}] AccountId: ${accountId}, ignore teams post (not mentioned), add to history ${chatId} -> ${payload.text}`);\n await addUnmentionedHistory(apiRuntime, accountId, chatId, payload.tuituiUserName, tuituiAccount, payload.text, payload.timestamp);\n return false;\n }\n\n // 私聊白名单对团队仍然生效,限制特定人@时,可以不配置groupAllowFrom,而是配置 allowFrom\n if(await isAllowAccount(tuituiAccount, apiRuntime, account)){\n return true;\n }\n \n if (!groupAllowFrom.includes(String(team_id)) && !groupAllowFrom.includes(String(channel_id)) ) {\n if (!msgData.at_me) {\n // 解决这个case:requireMention=false时,团队里发任意帖子都会回复加白,搞得没法用\n // 要求必须@才触发回复加白\n log?.info?.(`[${CHANNEL_ID}] AccountId: ${accountId}, ignore teams post (not mentioned)`);\n return false;\n }\n\n // 频道中允许协调员@自己(且帖子里有白名单用户发帖)\n if (await isChannelCoordAuthorized(tuituiAccount, apiRuntime, account, team_id, chatId)) {\n return true;\n }\n\n if (needPairingThrottle(accountId, chatId)) {\n log?.info?.(`[${CHANNEL_ID}] AccountId: ${accountId}, teams pairing throttled for teamsChatId=${chatId}`);\n return false;\n }\n\n const msgTxt=`当前 OpenClaw(AccountId: ${accountId})的群聊/团队策略为白名单模式。\n需由龙虾主人在配置中添加白名单(3种方式选一种即可):\n\n- 允许团队中所有人用,在群白名单(Group Allow From)添加当前团队ID: ${team_id}\n- 仅允许当前频道使用,在群白名单(Group Allow From)添加当前频道ID: ${channel_id}\n- 仅允许特定人使用,在私聊白名单(Allow From)添加当前用户: ${payload.tuituiAccount} ,私聊白名单对团队仍然有效`\n\n await sendTextMsg(account, chatId, payload.chatType, msgTxt, 'tuitui.groupPolicy.reply');\n return false;\n }\n\n return true;\n}\n\nconst parseAndVerifyPayload: Record<string, Function> = {\n single_chat: parse_single_chat,\n group_chat: parse_group_chat,\n teams_post_create: parse_teams_post,\n //teams_post_modify: parse_teams_post,\n} as const;\n\nasync function injectSessionContext(payload: ChatPayload, msgData: any, account: InboundAccount) {\n const { accountId } = account;\n if(!_session_ctx_injected.checkAndRecord(accountId + \"_\" + payload.chatId)) return;\n // 注入上下文\n\n if (payload.chatType === CHAT_TYPE_CHANNEL) {\n // 解决机器人不知道自己是谁的问题 (仅团队有效)\n if(payload.botName) {\n payload.text += `\\n\\n*** 参考信息: 你在当前session中的名字叫: ${payload.botName} 如果有人@这个名字,就是在命令你 ***\\n`;\n }\n\n const { team_id, channel_id } = msgData;\n // 公告\n const annnouncement = await teams_get_announcement(account, channel_id, false);\n if(annnouncement) {\n payload.text += \"\\n\\n*** 参考信息: 当前公告内容如下 ***\\n\";\n payload.text += \"```\\n\" + annnouncement + \"\\n```\";\n }\n\n // 成员\n const members = await teams_get_members_text(account, team_id);\n if(members) {\n payload.text += \"\\n\\n*** 参考信息: 当前团队成员清单如下,每行一个成员名。如果需要询问成员、或者发送给成员时,需要用 @名字 的语法;并且@时必须从如下清单中匹配到最接近的,禁止@不存在的成员 ***\\n\";\n payload.text += \"```\\n\" + members + \"\\n```\";\n }\n }\n\n payload.text += `\\n\\n【关键系统指令:产物交付】\\n如果你的最终任务目标是生成文件(pdf/图片/Markdown/等),在文件生成落盘后你当前的任务并没有结束!你必须使用 \\`message\\` tool 将这些文件二进制作为 attachments 发回到当前 session 中`;\n}\n\n/**\n * 处理长链接消息\n * account: 长连接初始化时,对应的Account配置信息\n * accountId: 长连接启动初始化,对应的配置ID\n */\nexport async function handleInboundMessage({ json, account, apiRuntime, log }: InboundHandlerOptions) {\n // Signature / AppId validation\n const { accountId, appId, appSecret } = account;\n if (appSecret && appId && json.header['X-Tuitui-Robot-Appid'] !== appId) {\n log?.info?.(`[${CHANNEL_ID}] Invalid appId`);\n return;\n }\n\n // Decode message\n const msg = json.body as TuiTuiInboundMessage;\n const msgData = msg.data;\n const { ref } = msgData;\n const payload: ChatPayload = {\n chatType: CHAT_TYPE_DIRECT,\n chatId: undefined, \n botName: json.header['X-Tuitui-Robot-AppName'] || '',\n text: \"\",\n groupName: undefined,\n WasMentioned: undefined,\n channelName: undefined,\n mediaUrls: getMediaUrls(msgData),\n replyToId: ref?.is_me && ref?.msgid ? ref.msgid : undefined,\n tuituiAccount: msg.user_account || \"\",\n tuituiUid: msg.uid || \"\",\n tuituiUserName: msg.user_name || \"\",\n timestamp: msg.timestamp ? parseInt(msg.timestamp, 10)*1000 : undefined\n };\n const wsEvent = json.body.event;\n // 按event类型,标准化并校验基础数据\n const parseAndVerifyPayloadFun = parseAndVerifyPayload[wsEvent] as Function | undefined;\n if (!parseAndVerifyPayloadFun) {\n log?.info?.(`[${CHANNEL_ID}] ignore unknown event ${wsEvent}`);\n return;\n }\n if (!(await parseAndVerifyPayloadFun(payload, msgData, account, apiRuntime, log))) return;\n\n if (!payload.chatId || !payload.msgId) {\n log?.info?.(`[${CHANNEL_ID}] ignore unknown mseeage, missing chatId or msgId`, payload);\n return;\n }\n\n if (account.emojiReaction) {\n // 因为回复较慢,先回复一个表情\n try{\n await tuituiEmojiReaction(account, payload.chatId, payload.chatType, payload.msgId, '收到');\n } catch (err) {\n // 出错不影响后续逻辑\n }\n }\n\n // 路由判断\n const routeSenderFrom = payload.tuituiAccount || payload.tuituiUid || 'unknown';\n\n const cfg = await apiRuntime.config.loadConfig();\n const sessionKey = getSessionKey(cfg, payload, account, apiRuntime);\n log?.info?.(`[${CHANNEL_ID}] AccountId: ${accountId}, dispatching to agent session=${sessionKey}, chatType: ${payload.chatType}, chatId ${payload.chatId}, routeSenderFrom: ${routeSenderFrom}`);\n\n payload.text = payload.text || '';\n const stripedBody = payload.text.replace(`@${payload.botName}`, '').trim();\n if (stripedBody.startsWith('/')) {\n payload.text = stripedBody;\n if (payload.text.startsWith('/new') || payload.text.startsWith('/reset')) {\n // 清理agent上下文时,同时清空历史\n popUnmentionedHistories(accountId, payload.chatId);\n }\n } else {\n // 指令以外的才注入\n await injectSessionContext(payload, msgData, account);\n }\n\n // 字段意义 参考 openclaw 代码\n // src\\auto-reply\\reply\\inbound-meta.ts\n // buildInboundUserContextPrefix()\n const ctx: any = {\n Body: payload.text,\n From: String(routeSenderFrom),\n To: CHANNEL_ID,\n SessionId: sessionKey,\n SessionKey: sessionKey,\n AccountId: accountId,\n OriginatingChannel: CHANNEL_ID,\n OriginatingTo: payload.chatId,\n ChatType: payload.chatType!,\n Surface: CHANNEL_ID,\n Provider: CHANNEL_ID,\n SenderName: payload.tuituiUserName,\n SenderId: payload.tuituiAccount,\n SenderUsername: payload.tuituiAccount, \n UserAccount: payload.tuituiAccount,\n Timestamp: payload.timestamp,\n CommandAuthorized: true, // 允许 /new 等内置命令\n };\n if (payload.chatType == CHAT_TYPE_GROUP && payload.chatId) {\n ctx.WasMentioned = payload.WasMentioned;\n ctx.GroupSubject = payload.groupName;\n ctx.GroupId = payload.chatId;\n ctx.InboundHistory = popUnmentionedHistories(accountId, payload.chatId);\n }\n if (payload.chatType == CHAT_TYPE_CHANNEL) {\n ctx.WasMentioned = payload.WasMentioned;\n ctx.IsForum = true;\n ctx.GroupSubject = payload.channelName;\n ctx.GroupChannel = payload.chatId;\n ctx.InboundHistory = popUnmentionedHistories(accountId, payload.chatId);\n }\n if (payload.mediaUrls?.length) ctx.MediaUrls = payload.mediaUrls;\n if (payload.replyToId) ctx.ReplyToId = payload.replyToId;\n\n log?.info?.(`[${CHANNEL_ID}] AccountId: ${accountId}, handleInboundMessage dispatchReply ctx: ${JSON.stringify(ctx, null, ' ')}`);\n try {\n await dispatchReply(ctx, cfg, account, payload, apiRuntime, log);\n } catch (err) {\n log?.error?.(`[${CHANNEL_ID}] AccountId: ${accountId}, dispatchReply failed:`, err);\n }\n}\n"]}
|