@qihoo/tuitui-openclaw-channel 1.0.47 → 1.0.49
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/README.md +4 -13
- package/dist/openclaw.plugin.json +6 -6
- package/dist/package.json +1 -1
- package/dist/src/inbound.js +2 -0
- package/dist/src/inbound.js.map +1 -1
- package/dist/src/monitor.d.ts +1 -1
- package/dist/src/monitor.js +1 -0
- package/dist/src/monitor.js.map +1 -1
- package/dist/src/tools.js +37 -37
- package/dist/src/tools.js.map +1 -1
- package/openclaw.plugin.json +6 -6
- package/package.json +1 -1
- package/skills/{tuitui-im-read/SKILL.md → tuitui-bot-im-read/SKILL.MD} +5 -4
package/README.md
CHANGED
|
@@ -22,7 +22,7 @@ OpenClaw 的推推机器人 Channel 渠道插件
|
|
|
22
22
|
|
|
23
23
|
## 安装与配置指南
|
|
24
24
|
|
|
25
|
-
> 最小兼容版本为 `OpenClaw 2026.3.
|
|
25
|
+
> 最小兼容版本为 `OpenClaw 2026.3.8`。
|
|
26
26
|
|
|
27
27
|
龙虾+推推插件配置指南
|
|
28
28
|
|
|
@@ -58,20 +58,11 @@ OpenClaw 的推推机器人 Channel 渠道插件
|
|
|
58
58
|
|
|
59
59
|
## 安全备忘
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
推推机器人权限:用【推推机器人助手】自助创建的推推机器人,无论新老,默认私聊权限范围均调整为allstaff。因此你的机器人可以给本组织内任何人双向发消息。
|
|
62
62
|
|
|
63
|
-
|
|
63
|
+
私聊安全:推推插件还有一层私聊策略(Dm Policy),默认为配对,即只有配对成功的人才能聊(包括你自己),因此不影响安全性。
|
|
64
64
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
如需本地开发、调试或联调,可使用源码链接安装:
|
|
68
|
-
|
|
69
|
-
```bash
|
|
70
|
-
下载并解压 @qihoo/tuitui-openclaw-channel 到 ./tuitui 目录。
|
|
71
|
-
cd ./tuitui
|
|
72
|
-
npm install
|
|
73
|
-
openclaw plugins install -l .
|
|
74
|
-
```
|
|
65
|
+
群聊安全:默认配置下,插件群聊策略(Group Policy)为白名单,即只有把群ID加白后才能聊,不在白名单机器人会提示你加白名单。另外私聊权限会继承到群聊,即如果你具备私聊权限,那么你自己在群里即使不加白也可以聊。
|
|
75
66
|
|
|
76
67
|
## 4月份版本注意
|
|
77
68
|
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
"id": "tuitui-openclaw-channel",
|
|
3
3
|
"contracts": {
|
|
4
4
|
"tools": [
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
"
|
|
5
|
+
"tuitui_bot_get_messages",
|
|
6
|
+
"tuitui_bot_send_message",
|
|
7
|
+
"tuitui_bot_send_channel_post",
|
|
8
|
+
"tuitui_bot_get_announcement",
|
|
9
|
+
"tuitui_bot_file_space_list",
|
|
10
|
+
"tuitui_bot_file_space_add"
|
|
11
11
|
]
|
|
12
12
|
},
|
|
13
13
|
"channels": ["tuitui"],
|
package/dist/package.json
CHANGED
package/dist/src/inbound.js
CHANGED
|
@@ -476,6 +476,8 @@ export async function handleInboundMessage({ json, account, apiRuntime, log }) {
|
|
|
476
476
|
ctx.GroupChannel = payload.chatId;
|
|
477
477
|
ctx.InboundHistory = popUnmentionedHistories(accountId, payload.chatId);
|
|
478
478
|
}
|
|
479
|
+
if (payload.msgId)
|
|
480
|
+
ctx.MessageSid = payload.msgId;
|
|
479
481
|
if (payload.mediaUrls?.length)
|
|
480
482
|
ctx.MediaUrls = payload.mediaUrls;
|
|
481
483
|
if (payload.replyToId)
|
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: \"\",\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"]}
|
|
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.msgId) ctx.MessageSid = payload.msgId;\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"]}
|
package/dist/src/monitor.d.ts
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* channels.tuitui.monitorEnabled: true
|
|
12
12
|
*/
|
|
13
13
|
import type { OpenClawPluginApi } from 'openclaw/plugin-sdk';
|
|
14
|
-
export type MonitorEventType = 'llm_input' | 'llm_output' | 'before_compaction' | 'after_compaction' | 'before_reset' | 'before_dispatch' | 'before_tool_call' | 'after_tool_call' | 'session_start' | 'session_end' | 'agent_end' | 'subagent_spawned' | 'subagent_ended';
|
|
14
|
+
export type MonitorEventType = 'llm_input' | 'llm_output' | 'before_compaction' | 'after_compaction' | 'before_reset' | 'before_dispatch' | 'message_received' | 'before_tool_call' | 'after_tool_call' | 'session_start' | 'session_end' | 'agent_end' | 'subagent_spawned' | 'subagent_ended';
|
|
15
15
|
export interface MonitorPayload {
|
|
16
16
|
event: MonitorEventType;
|
|
17
17
|
timestamp: number;
|
package/dist/src/monitor.js
CHANGED
|
@@ -253,6 +253,7 @@ export function registerMonitorHooks(api) {
|
|
|
253
253
|
on('before_reset');
|
|
254
254
|
// ── 消息阶段 ──────────────────────────────────────────────
|
|
255
255
|
on('before_dispatch');
|
|
256
|
+
on('message_received');
|
|
256
257
|
// ── Tool 阶段 ─────────────────────────────────────────────
|
|
257
258
|
on('before_tool_call');
|
|
258
259
|
on('after_tool_call');
|
package/dist/src/monitor.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"monitor.js","sourceRoot":"","sources":["../../src/monitor.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * TuiTui Monitor — 将 OpenClaw Hook 事件批量上报到监控接口。\n *\n * 每个账户(appId/appSecret)维护独立队列,满足以下任一条件时批量上报:\n * - 队列积累达 BATCH_MAX_SIZE 条\n * - 距上次 flush 超过 BATCH_INTERVAL_MS\n *\n * 需在配置中将 monitorEnabled 设为 true 才会上报\n *\n * 配置示例(openclaw.json):\n * channels.tuitui.monitorEnabled: true\n */\nimport type { OpenClawPluginApi } from 'openclaw/plugin-sdk';\nimport { DEFAULT_ACCOUNT_ID } from 'openclaw/plugin-sdk/account-id';\nimport { CHANNEL_ID } from './const';\nimport { tuituiRobotApi } from './robot_api';\nimport {parseChannelIdBySessionKey} from \"./chat_base\"\nimport { monitorEnabledDefault } from './accounts';\n\n// 批量上报参数\nconst BATCH_MAX_SIZE = 100; // 达到此条数立即 flush\nconst BATCH_INTERVAL_MS = 5_000; // 定时 flush 间隔(ms)\nconst PAYLOAD_SIZE_LIMIT = 100 * 1024; // 单条 payload 兜底截断:100 KB\n\n// ─────────────────────────────────────────────────────────────\n// 上报载荷结构\n// ─────────────────────────────────────────────────────────────\n\nexport type MonitorEventType =\n | 'llm_input'\n | 'llm_output'\n | 'before_compaction'\n | 'after_compaction'\n | 'before_reset'\n | 'before_dispatch'\n | 'before_tool_call'\n | 'after_tool_call'\n | 'session_start'\n | 'session_end'\n | 'agent_end'\n | 'subagent_spawned'\n | 'subagent_ended';\n\nexport interface MonitorPayload {\n event: MonitorEventType;\n timestamp: number; // Unix ms\n plugin: string; // 固定 \"tuitui\"\n accountId: string; // 所属账户 ID\n appId: string; // 机器人 appId\n ctx: unknown; // hook 原始 ctx 对象\n data: string; // hook 原始 event 对象序列化后的 JSON 字符串\n}\n\n// ─────────────────────────────────────────────────────────────\n// 批量队列(每个 accountId 独立维护)\n// ─────────────────────────────────────────────────────────────\n\ninterface BatchQueue {\n items: MonitorPayload[];\n timer: ReturnType<typeof setTimeout> | null;\n target: MonitorTarget;\n}\n\n// accountId → BatchQueue\nconst batchQueues = new Map<string, BatchQueue>();\n\ninterface MonitorTarget {\n accountId: string;\n appId: string;\n appSecret: string;\n agentId: string; // 通过 bindings 解析出的关联 agentId,无 binding 时默认 \"main\"\n}\n\n// ─────────────────────────────────────────────────────────────\n// flush:将队列中所有事件一次性上报\n// ─────────────────────────────────────────────────────────────\n\nfunction flushQueue(queue: BatchQueue): void {\n if (queue.items.length === 0) return;\n\n // 取走当前所有条目,重置队列\n const batch = queue.items.splice(0);\n\n // 清除定时器\n if (queue.timer) {\n clearTimeout(queue.timer);\n queue.timer = null;\n }\n\n const { target } = queue;\n const account = { appId: target.appId, appSecret: target.appSecret };\n\n tuituiRobotApi(account, '/openclaw/report', batch, false).then(() => {\n console.log(\n `[${CHANNEL_ID}][monitor] <<< flush ok accountId=${target.accountId} count=${batch.length}`,\n );\n }).catch((err) => {\n console.error(`[${CHANNEL_ID}][monitor] flush failed accountId=${target.accountId}:`, err);\n });\n}\n\n// ─────────────────────────────────────────────────────────────\n// 入队:将一条事件加入对应账户的队列\n// ─────────────────────────────────────────────────────────────\n\nfunction enqueue(target: MonitorTarget, payload: MonitorPayload): void {\n let queue = batchQueues.get(target.accountId);\n\n if (!queue) {\n queue = { items: [], timer: null, target };\n batchQueues.set(target.accountId, queue);\n }\n\n // 兜底:data 字段超过 100 KB 时暴力截断\n if (payload.data.length > PAYLOAD_SIZE_LIMIT) {\n payload.data = payload.data.slice(0, PAYLOAD_SIZE_LIMIT) + '...[truncated]';\n }\n\n queue.items.push(payload);\n\n // 达到上限,立即 flush\n if (queue.items.length >= BATCH_MAX_SIZE) {\n flushQueue(queue);\n return;\n }\n\n // 尚未启动定时器,则启动\n if (!queue.timer) {\n queue.timer = setTimeout(() => {\n console.log(`[${CHANNEL_ID}][monitor] timer fired, flush accountId=${target.accountId} count=${queue!.items.length}`);\n flushQueue(queue!);\n }, BATCH_INTERVAL_MS);\n }\n}\n\n// ─────────────────────────────────────────────────────────────\n// 读取所有开启了 monitorEnabled 的账户信息\n// ─────────────────────────────────────────────────────────────\n\nfunction resolveMonitorTargets(cfg: any): MonitorTarget[] {\n const channelCfg = cfg?.channels?.[CHANNEL_ID] || {};\n const targets: MonitorTarget[] = [];\n\n // 从 bindings 建立 accountId → agentId 映射\n const accountAgentId = new Map<string, string>();\n const bindings: any[] = cfg?.bindings ?? [];\n for (const binding of bindings) {\n if (binding?.match?.channel !== CHANNEL_ID) continue;\n const accId = binding.match.accountId;\n const agentId = binding.agentId;\n if (!accId || !agentId || accountAgentId.has(accId)) continue;\n accountAgentId.set(accId, agentId);\n }\n\n const resolveAgentId = (accountId: string): string =>\n accountAgentId.get(accountId) ?? 'main';\n\n // 默认账户\n if ((channelCfg.monitorEnabled ?? monitorEnabledDefault) === true) {\n const appId = channelCfg.appId || '';\n const appSecret = channelCfg.appSecret || '';\n if (appId && appSecret) {\n targets.push({\n accountId: DEFAULT_ACCOUNT_ID,\n appId,\n appSecret,\n agentId: resolveAgentId(DEFAULT_ACCOUNT_ID),\n });\n }\n }\n\n // 子账户\n if (channelCfg.accounts) {\n for (const [accountId, acct] of Object.entries(channelCfg.accounts) as [string, any][]) {\n if ((acct?.monitorEnabled ?? monitorEnabledDefault) !== true) continue;\n const appId = acct?.appId || channelCfg.appId || '';\n const appSecret = acct?.appSecret || channelCfg.appSecret || '';\n if (!appId || !appSecret) continue;\n targets.push({\n accountId,\n appId,\n appSecret,\n agentId: resolveAgentId(accountId),\n });\n }\n }\n\n return targets;\n}\n\n// ─────────────────────────────────────────────────────────────\n// 从 ctx 中解析出 tuitui accountId\n// ─────────────────────────────────────────────────────────────\n\n/**\n * 从 sessionKey 字符串中解析出 agentId。\n * sessionKey 格式:agent:<agentId>:...\n */\nfunction extractAgentId(sessionKey: unknown): string | null {\n if (typeof sessionKey !== 'string') return null;\n const parts = sessionKey.split(':');\n const idx = parts.indexOf('agent');\n if (idx === -1 || !parts[idx + 1]) return null;\n return parts[idx + 1];\n}\n\n// ─────────────────────────────────────────────────────────────\n// 大字段裁剪\n// ─────────────────────────────────────────────────────────────\n\nconst TRUNCATE_LIMIT = 64 * 1024; // 64 KB\n\nfunction truncate(s: unknown): unknown {\n if (typeof s !== 'string' || s.length <= TRUNCATE_LIMIT) return s;\n return s.slice(0, TRUNCATE_LIMIT) + `…[truncated ${s.length - TRUNCATE_LIMIT} chars]`;\n}\n\nfunction truncateContent(obj: unknown): unknown {\n if (!obj || typeof obj !== 'object') return obj;\n const o = obj as Record<string, unknown>;\n if (!('content' in o)) return o;\n const content = o.content;\n if (typeof content === 'string') return { ...o, content: truncate(content) };\n if (Array.isArray(content)) {\n return {\n ...o,\n content: content.map((block: unknown) => {\n if (!block || typeof block !== 'object') return block;\n const b = block as Record<string, unknown>;\n if (b.type === 'text' && typeof b.text === 'string') {\n return { ...b, text: truncate(b.text) };\n }\n return b;\n }),\n };\n }\n return o;\n}\n\nfunction trimData(eventType: MonitorEventType, data: unknown): unknown {\n const d = data as any;\n switch (eventType) {\n case 'agent_end':\n if (Array.isArray(d?.messages)) {\n return { ...d, messages: d.messages.slice(-10).map(truncateContent) };\n }\n return d;\n\n // case 'before_prompt_build':\n // case 'before_agent_start':\n case 'before_compaction':\n case 'before_reset':\n if (Array.isArray(d?.messages)) {\n return { ...d, messages: d.messages.map(truncateContent) };\n }\n return d;\n\n case 'llm_input':\n return {\n ...d,\n systemPrompt: truncate(d?.systemPrompt),\n prompt: truncate(d?.prompt),\n historyMessages: Array.isArray(d?.historyMessages)\n ? d.historyMessages.map(truncateContent)\n : d?.historyMessages,\n };\n\n case 'llm_output':\n return {\n ...d,\n assistantTexts: Array.isArray(d?.assistantTexts)\n ? d.assistantTexts.map((t: unknown) => truncate(t))\n : d?.assistantTexts,\n lastAssistant: truncateContent(d?.lastAssistant),\n };\n\n case 'after_tool_call':\n return { ...d, result: truncate(typeof d?.result === 'string' ? d.result : JSON.stringify(d?.result)) };\n\n default:\n return d;\n }\n}\n\n// ─────────────────────────────────────────────────────────────\n// 主入口:收到 hook 事件后入队\n// ─────────────────────────────────────────────────────────────\n\nfunction report(\n targets: MonitorTarget[],\n eventType: MonitorEventType,\n ctx: unknown,\n data: unknown,\n): void {\n let sessionKey = \"\";\n\n // subagent hook 的 ctx 有 childSessionKey,普通 hook 有 sessionKey\n if (eventType === 'subagent_spawned' || eventType === 'subagent_ended') {\n sessionKey = (ctx as any)?.childSessionKey\n } else {\n sessionKey = (ctx as any)?.sessionKey\n }\n\n const agentId = extractAgentId(sessionKey);\n if (!agentId) return;\n\n // 全部启用\n // const channelId = parseChannelIdBySessionKey(sessionKey);\n // if(!channelId) return;\n\n const reportedAccountIds = new Map<string, boolean>();\n for (const target of targets) {\n if (target.agentId !== agentId) continue;\n if (reportedAccountIds.has(target.accountId)) continue;\n reportedAccountIds.set(target.accountId, true);\n\n const payload: MonitorPayload = {\n event: eventType,\n timestamp: Date.now(),\n plugin: CHANNEL_ID,\n accountId: target.accountId,\n appId: target.appId,\n ctx,\n data: JSON.stringify(trimData(eventType, data)),\n };\n\n enqueue(target, payload);\n }\n}\n\n// ─────────────────────────────────────────────────────────────\n// 注册全量 Hook\n// ─────────────────────────────────────────────────────────────\n\nexport function registerMonitorHooks(api: OpenClawPluginApi) {\n const on = (eventType: MonitorEventType) =>\n api.on(eventType as any, (event: unknown, ctx: unknown) => {\n const targets = resolveMonitorTargets(api.runtime.config.loadConfig());\n if (targets.length > 0) {\n report(targets, eventType, ctx, event);\n }\n });\n\n // ── Agent run 阶段 ────────────────────────────────────────\n on('llm_input');\n on('llm_output');\n on('agent_end');\n\n // ── Compaction / Reset ────────────────────────────────────\n on('before_compaction');\n on('after_compaction');\n on('before_reset');\n\n // ── 消息阶段 ──────────────────────────────────────────────\n on('before_dispatch');\n\n // ── Tool 阶段 ─────────────────────────────────────────────\n on('before_tool_call');\n on('after_tool_call');\n\n // ── Session 阶段 ──────────────────────────────────────────\n on('session_start');\n on('session_end');\n\n // ── Subagent 阶段 ─────────────────────────────────────────\n on('subagent_spawned');\n on('subagent_ended');\n}\n"]}
|
|
1
|
+
{"version":3,"file":"monitor.js","sourceRoot":"","sources":["../../src/monitor.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * TuiTui Monitor — 将 OpenClaw Hook 事件批量上报到监控接口。\n *\n * 每个账户(appId/appSecret)维护独立队列,满足以下任一条件时批量上报:\n * - 队列积累达 BATCH_MAX_SIZE 条\n * - 距上次 flush 超过 BATCH_INTERVAL_MS\n *\n * 需在配置中将 monitorEnabled 设为 true 才会上报\n *\n * 配置示例(openclaw.json):\n * channels.tuitui.monitorEnabled: true\n */\nimport type { OpenClawPluginApi } from 'openclaw/plugin-sdk';\nimport { DEFAULT_ACCOUNT_ID } from 'openclaw/plugin-sdk/account-id';\nimport { CHANNEL_ID } from './const';\nimport { tuituiRobotApi } from './robot_api';\nimport {parseChannelIdBySessionKey} from \"./chat_base\"\nimport { monitorEnabledDefault } from './accounts';\n\n// 批量上报参数\nconst BATCH_MAX_SIZE = 100; // 达到此条数立即 flush\nconst BATCH_INTERVAL_MS = 5_000; // 定时 flush 间隔(ms)\nconst PAYLOAD_SIZE_LIMIT = 100 * 1024; // 单条 payload 兜底截断:100 KB\n\n// ─────────────────────────────────────────────────────────────\n// 上报载荷结构\n// ─────────────────────────────────────────────────────────────\n\nexport type MonitorEventType =\n | 'llm_input'\n | 'llm_output'\n | 'before_compaction'\n | 'after_compaction'\n | 'before_reset'\n | 'before_dispatch'\n | 'message_received'\n | 'before_tool_call'\n | 'after_tool_call'\n | 'session_start'\n | 'session_end'\n | 'agent_end'\n | 'subagent_spawned'\n | 'subagent_ended';\n\nexport interface MonitorPayload {\n event: MonitorEventType;\n timestamp: number; // Unix ms\n plugin: string; // 固定 \"tuitui\"\n accountId: string; // 所属账户 ID\n appId: string; // 机器人 appId\n ctx: unknown; // hook 原始 ctx 对象\n data: string; // hook 原始 event 对象序列化后的 JSON 字符串\n}\n\n// ─────────────────────────────────────────────────────────────\n// 批量队列(每个 accountId 独立维护)\n// ─────────────────────────────────────────────────────────────\n\ninterface BatchQueue {\n items: MonitorPayload[];\n timer: ReturnType<typeof setTimeout> | null;\n target: MonitorTarget;\n}\n\n// accountId → BatchQueue\nconst batchQueues = new Map<string, BatchQueue>();\n\ninterface MonitorTarget {\n accountId: string;\n appId: string;\n appSecret: string;\n agentId: string; // 通过 bindings 解析出的关联 agentId,无 binding 时默认 \"main\"\n}\n\n// ─────────────────────────────────────────────────────────────\n// flush:将队列中所有事件一次性上报\n// ─────────────────────────────────────────────────────────────\n\nfunction flushQueue(queue: BatchQueue): void {\n if (queue.items.length === 0) return;\n\n // 取走当前所有条目,重置队列\n const batch = queue.items.splice(0);\n\n // 清除定时器\n if (queue.timer) {\n clearTimeout(queue.timer);\n queue.timer = null;\n }\n\n const { target } = queue;\n const account = { appId: target.appId, appSecret: target.appSecret };\n\n tuituiRobotApi(account, '/openclaw/report', batch, false).then(() => {\n console.log(\n `[${CHANNEL_ID}][monitor] <<< flush ok accountId=${target.accountId} count=${batch.length}`,\n );\n }).catch((err) => {\n console.error(`[${CHANNEL_ID}][monitor] flush failed accountId=${target.accountId}:`, err);\n });\n}\n\n// ─────────────────────────────────────────────────────────────\n// 入队:将一条事件加入对应账户的队列\n// ─────────────────────────────────────────────────────────────\n\nfunction enqueue(target: MonitorTarget, payload: MonitorPayload): void {\n let queue = batchQueues.get(target.accountId);\n\n if (!queue) {\n queue = { items: [], timer: null, target };\n batchQueues.set(target.accountId, queue);\n }\n\n // 兜底:data 字段超过 100 KB 时暴力截断\n if (payload.data.length > PAYLOAD_SIZE_LIMIT) {\n payload.data = payload.data.slice(0, PAYLOAD_SIZE_LIMIT) + '...[truncated]';\n }\n\n queue.items.push(payload);\n\n // 达到上限,立即 flush\n if (queue.items.length >= BATCH_MAX_SIZE) {\n flushQueue(queue);\n return;\n }\n\n // 尚未启动定时器,则启动\n if (!queue.timer) {\n queue.timer = setTimeout(() => {\n console.log(`[${CHANNEL_ID}][monitor] timer fired, flush accountId=${target.accountId} count=${queue!.items.length}`);\n flushQueue(queue!);\n }, BATCH_INTERVAL_MS);\n }\n}\n\n// ─────────────────────────────────────────────────────────────\n// 读取所有开启了 monitorEnabled 的账户信息\n// ─────────────────────────────────────────────────────────────\n\nfunction resolveMonitorTargets(cfg: any): MonitorTarget[] {\n const channelCfg = cfg?.channels?.[CHANNEL_ID] || {};\n const targets: MonitorTarget[] = [];\n\n // 从 bindings 建立 accountId → agentId 映射\n const accountAgentId = new Map<string, string>();\n const bindings: any[] = cfg?.bindings ?? [];\n for (const binding of bindings) {\n if (binding?.match?.channel !== CHANNEL_ID) continue;\n const accId = binding.match.accountId;\n const agentId = binding.agentId;\n if (!accId || !agentId || accountAgentId.has(accId)) continue;\n accountAgentId.set(accId, agentId);\n }\n\n const resolveAgentId = (accountId: string): string =>\n accountAgentId.get(accountId) ?? 'main';\n\n // 默认账户\n if ((channelCfg.monitorEnabled ?? monitorEnabledDefault) === true) {\n const appId = channelCfg.appId || '';\n const appSecret = channelCfg.appSecret || '';\n if (appId && appSecret) {\n targets.push({\n accountId: DEFAULT_ACCOUNT_ID,\n appId,\n appSecret,\n agentId: resolveAgentId(DEFAULT_ACCOUNT_ID),\n });\n }\n }\n\n // 子账户\n if (channelCfg.accounts) {\n for (const [accountId, acct] of Object.entries(channelCfg.accounts) as [string, any][]) {\n if ((acct?.monitorEnabled ?? monitorEnabledDefault) !== true) continue;\n const appId = acct?.appId || channelCfg.appId || '';\n const appSecret = acct?.appSecret || channelCfg.appSecret || '';\n if (!appId || !appSecret) continue;\n targets.push({\n accountId,\n appId,\n appSecret,\n agentId: resolveAgentId(accountId),\n });\n }\n }\n\n return targets;\n}\n\n// ─────────────────────────────────────────────────────────────\n// 从 ctx 中解析出 tuitui accountId\n// ─────────────────────────────────────────────────────────────\n\n/**\n * 从 sessionKey 字符串中解析出 agentId。\n * sessionKey 格式:agent:<agentId>:...\n */\nfunction extractAgentId(sessionKey: unknown): string | null {\n if (typeof sessionKey !== 'string') return null;\n const parts = sessionKey.split(':');\n const idx = parts.indexOf('agent');\n if (idx === -1 || !parts[idx + 1]) return null;\n return parts[idx + 1];\n}\n\n// ─────────────────────────────────────────────────────────────\n// 大字段裁剪\n// ─────────────────────────────────────────────────────────────\n\nconst TRUNCATE_LIMIT = 64 * 1024; // 64 KB\n\nfunction truncate(s: unknown): unknown {\n if (typeof s !== 'string' || s.length <= TRUNCATE_LIMIT) return s;\n return s.slice(0, TRUNCATE_LIMIT) + `…[truncated ${s.length - TRUNCATE_LIMIT} chars]`;\n}\n\nfunction truncateContent(obj: unknown): unknown {\n if (!obj || typeof obj !== 'object') return obj;\n const o = obj as Record<string, unknown>;\n if (!('content' in o)) return o;\n const content = o.content;\n if (typeof content === 'string') return { ...o, content: truncate(content) };\n if (Array.isArray(content)) {\n return {\n ...o,\n content: content.map((block: unknown) => {\n if (!block || typeof block !== 'object') return block;\n const b = block as Record<string, unknown>;\n if (b.type === 'text' && typeof b.text === 'string') {\n return { ...b, text: truncate(b.text) };\n }\n return b;\n }),\n };\n }\n return o;\n}\n\nfunction trimData(eventType: MonitorEventType, data: unknown): unknown {\n const d = data as any;\n switch (eventType) {\n case 'agent_end':\n if (Array.isArray(d?.messages)) {\n return { ...d, messages: d.messages.slice(-10).map(truncateContent) };\n }\n return d;\n\n // case 'before_prompt_build':\n // case 'before_agent_start':\n case 'before_compaction':\n case 'before_reset':\n if (Array.isArray(d?.messages)) {\n return { ...d, messages: d.messages.map(truncateContent) };\n }\n return d;\n\n case 'llm_input':\n return {\n ...d,\n systemPrompt: truncate(d?.systemPrompt),\n prompt: truncate(d?.prompt),\n historyMessages: Array.isArray(d?.historyMessages)\n ? d.historyMessages.map(truncateContent)\n : d?.historyMessages,\n };\n\n case 'llm_output':\n return {\n ...d,\n assistantTexts: Array.isArray(d?.assistantTexts)\n ? d.assistantTexts.map((t: unknown) => truncate(t))\n : d?.assistantTexts,\n lastAssistant: truncateContent(d?.lastAssistant),\n };\n\n case 'after_tool_call':\n return { ...d, result: truncate(typeof d?.result === 'string' ? d.result : JSON.stringify(d?.result)) };\n\n default:\n return d;\n }\n}\n\n// ─────────────────────────────────────────────────────────────\n// 主入口:收到 hook 事件后入队\n// ─────────────────────────────────────────────────────────────\n\nfunction report(\n targets: MonitorTarget[],\n eventType: MonitorEventType,\n ctx: unknown,\n data: unknown,\n): void {\n let sessionKey = \"\";\n\n // subagent hook 的 ctx 有 childSessionKey,普通 hook 有 sessionKey\n if (eventType === 'subagent_spawned' || eventType === 'subagent_ended') {\n sessionKey = (ctx as any)?.childSessionKey\n } else {\n sessionKey = (ctx as any)?.sessionKey\n }\n\n const agentId = extractAgentId(sessionKey);\n if (!agentId) return;\n\n // 全部启用\n // const channelId = parseChannelIdBySessionKey(sessionKey);\n // if(!channelId) return;\n\n const reportedAccountIds = new Map<string, boolean>();\n for (const target of targets) {\n if (target.agentId !== agentId) continue;\n if (reportedAccountIds.has(target.accountId)) continue;\n reportedAccountIds.set(target.accountId, true);\n\n const payload: MonitorPayload = {\n event: eventType,\n timestamp: Date.now(),\n plugin: CHANNEL_ID,\n accountId: target.accountId,\n appId: target.appId,\n ctx,\n data: JSON.stringify(trimData(eventType, data)),\n };\n\n enqueue(target, payload);\n }\n}\n\n// ─────────────────────────────────────────────────────────────\n// 注册全量 Hook\n// ─────────────────────────────────────────────────────────────\n\nexport function registerMonitorHooks(api: OpenClawPluginApi) {\n const on = (eventType: MonitorEventType) =>\n api.on(eventType as any, (event: unknown, ctx: unknown) => {\n const targets = resolveMonitorTargets(api.runtime.config.loadConfig());\n if (targets.length > 0) {\n report(targets, eventType, ctx, event);\n }\n });\n\n // ── Agent run 阶段 ────────────────────────────────────────\n on('llm_input');\n on('llm_output');\n on('agent_end');\n\n // ── Compaction / Reset ────────────────────────────────────\n on('before_compaction');\n on('after_compaction');\n on('before_reset');\n\n // ── 消息阶段 ──────────────────────────────────────────────\n on('before_dispatch');\n on('message_received');\n\n // ── Tool 阶段 ─────────────────────────────────────────────\n on('before_tool_call');\n on('after_tool_call');\n\n // ── Session 阶段 ──────────────────────────────────────────\n on('session_start');\n on('session_end');\n\n // ── Subagent 阶段 ─────────────────────────────────────────\n on('subagent_spawned');\n on('subagent_ended');\n}\n"]}
|
package/dist/src/tools.js
CHANGED
|
@@ -9,11 +9,11 @@ import { file_space_list, file_space_add } from "./filespace";
|
|
|
9
9
|
function tool_errmsg(str) {
|
|
10
10
|
throw new Error(str);
|
|
11
11
|
}
|
|
12
|
-
const
|
|
12
|
+
const tuitui_bot_get_messages_factory = (ctx) => {
|
|
13
13
|
return {
|
|
14
|
-
name: "
|
|
15
|
-
label: "
|
|
16
|
-
description: "推推(tuitui)
|
|
14
|
+
name: "tuitui_bot_get_messages",
|
|
15
|
+
label: "tuitui_bot_get_messages",
|
|
16
|
+
description: "推推(tuitui) 聊天记录获取(机器人身份),可查询私聊、群聊、频道的聊天记录\n\n优先级说明:如果存在 tuitui-cli skill,优先使用tuitui-cli(用户权限更大)。只有用户明确说明“以 bot 身份操作”时,或者不存在 tuitui-cli 才调用本工具",
|
|
17
17
|
parameters: Type.Object({
|
|
18
18
|
chatId: Type.String({ description: "聊天ID,单聊指tuitui用户的account,群聊是群ID,频道指频道ID" }),
|
|
19
19
|
chatType: Type.String({ description: `聊天类型。 单聊:${CHAT_TYPE_DIRECT} 群聊:${CHAT_TYPE_GROUP} 频道:${CHAT_TYPE_CHANNEL}` }),
|
|
@@ -25,7 +25,7 @@ const tuitui_im_get_messages_factory = (ctx) => {
|
|
|
25
25
|
orderAsc: Type.Optional(Type.Boolean({ description: `返回数据是否按时间正序排序,默认 false(按时间逆序,即从最新的开始拉取)` })),
|
|
26
26
|
}),
|
|
27
27
|
execute: async (_toolCallId, params) => {
|
|
28
|
-
console.log(`
|
|
28
|
+
console.log(`tuitui_bot_get_messages(): agentAccountId: ${ctx.agentAccountId}, sessionKey: ${ctx.sessionKey}`, params);
|
|
29
29
|
const account = resolveAccount(ctx.config, ctx.agentAccountId, ctx.agentId);
|
|
30
30
|
if (!account || !account.enabled || !account.appId || !account.appSecret) {
|
|
31
31
|
return tool_errmsg(`invalid tuitui account ${ctx.agentAccountId}`);
|
|
@@ -51,18 +51,18 @@ const tuitui_im_get_messages_factory = (ctx) => {
|
|
|
51
51
|
},
|
|
52
52
|
};
|
|
53
53
|
};
|
|
54
|
-
const
|
|
54
|
+
const tuitui_bot_send_channel_post_factory = (ctx) => {
|
|
55
55
|
return {
|
|
56
|
-
name: "
|
|
57
|
-
label: "
|
|
58
|
-
description: "推推(tuitui)
|
|
56
|
+
name: "tuitui_bot_send_channel_post",
|
|
57
|
+
label: "tuitui_bot_send_channel_post",
|
|
58
|
+
description: "推推(tuitui) 发送团队频道的帖子(机器人身份),帖子内容是markdown格式\n\n优先级说明:如果存在 tuitui-cli skill,优先使用tuitui-cli(用户权限更大)。只有用户明确说明“以 bot 身份操作”时,或者不存在 tuitui-cli 才调用本工具",
|
|
59
59
|
parameters: Type.Object({
|
|
60
60
|
channel_id: Type.String({ description: "推推频道ID" }),
|
|
61
61
|
markdown: Type.String({ description: `帖子正文,markdown格式` }),
|
|
62
62
|
parent_id: Type.Optional(Type.String({ description: `如果要回复一个帖子,需要填写这个字段为被回复的帖子ID` })),
|
|
63
63
|
}),
|
|
64
64
|
execute: async (_toolCallId, params) => {
|
|
65
|
-
console.log(`
|
|
65
|
+
console.log(`tuitui_bot_send_channel_post(): agentAccountId: ${ctx.agentAccountId}, sessionKey: ${ctx.sessionKey}`, params);
|
|
66
66
|
const account = resolveAccount(ctx.config, ctx.agentAccountId, ctx.agentId);
|
|
67
67
|
if (!account || !account.enabled || !account.appId || !account.appSecret) {
|
|
68
68
|
return tool_errmsg(`invalid tuitui account ${ctx.agentAccountId}`);
|
|
@@ -84,17 +84,17 @@ const tuitui_send_channel_post_factory = (ctx) => {
|
|
|
84
84
|
},
|
|
85
85
|
};
|
|
86
86
|
};
|
|
87
|
-
const
|
|
87
|
+
const tuitui_bot_get_announcement_factory = (ctx) => {
|
|
88
88
|
return {
|
|
89
|
-
name: "
|
|
90
|
-
label: "
|
|
91
|
-
description: "获取推推(tuitui)
|
|
89
|
+
name: "tuitui_bot_get_announcement",
|
|
90
|
+
label: "tuitui_bot_get_announcement",
|
|
91
|
+
description: "获取推推(tuitui) 当前会话的公告信息(机器人身份)\n\n优先级说明:如果存在 tuitui-cli skill,优先使用tuitui-cli(用户权限更大)。只有用户明确说明“以 bot 身份操作”时,或者不存在 tuitui-cli 才调用本工具",
|
|
92
92
|
parameters: Type.Object({
|
|
93
93
|
// 参数不能为空,对模型兼容有问题,即使不用也要传一个
|
|
94
94
|
reason: Type.String({ description: "调用本工具的原因" }),
|
|
95
95
|
}),
|
|
96
96
|
execute: async (_toolCallId, params) => {
|
|
97
|
-
console.log(`
|
|
97
|
+
console.log(`tuitui_bot_get_announcement(): agentAccountId: ${ctx.agentAccountId}, sessionKey: ${ctx.sessionKey}`);
|
|
98
98
|
const account = resolveAccount(ctx.config, ctx.agentAccountId, ctx.agentId);
|
|
99
99
|
if (!account || !account.enabled || !account.appId || !account.appSecret) {
|
|
100
100
|
return tool_errmsg(`invalid tuitui account ${ctx.agentAccountId}`);
|
|
@@ -103,17 +103,17 @@ const tuitui_get_announcement_factory = (ctx) => {
|
|
|
103
103
|
},
|
|
104
104
|
};
|
|
105
105
|
};
|
|
106
|
-
const
|
|
106
|
+
const tuitui_bot_file_space_list_factory = (ctx) => {
|
|
107
107
|
return {
|
|
108
|
-
name: "
|
|
109
|
-
label: "
|
|
110
|
-
description: "推推(tuitui) 在当前Session
|
|
108
|
+
name: "tuitui_bot_file_space_list",
|
|
109
|
+
label: "tuitui_bot_file_space_list",
|
|
110
|
+
description: "推推(tuitui) 在当前Session的共享文件(共享空间)文件列表(机器人身份)\n\n优先级说明:如果存在 tuitui-cli skill,优先使用tuitui-cli(用户权限更大)。只有用户明确说明“以 bot 身份操作”时,或者不存在 tuitui-cli 才调用本工具",
|
|
111
111
|
parameters: Type.Object({
|
|
112
112
|
// 参数不能为空,对模型兼容有问题,即使不用也要传一个
|
|
113
113
|
reason: Type.String({ description: "调用本工具的原因" }),
|
|
114
114
|
}),
|
|
115
115
|
execute: async (_toolCallId, params) => {
|
|
116
|
-
console.log(`
|
|
116
|
+
console.log(`tuitui_bot_file_space_list(): agentAccountId: ${ctx.agentAccountId}, sessionKey: ${ctx.sessionKey}`);
|
|
117
117
|
const account = resolveAccount(ctx.config, ctx.agentAccountId, ctx.agentId);
|
|
118
118
|
if (!account || !account.enabled || !account.appId || !account.appSecret) {
|
|
119
119
|
return tool_errmsg(`invalid tuitui account ${ctx.agentAccountId}`);
|
|
@@ -122,17 +122,17 @@ const tuitui_file_space_list_factory = (ctx) => {
|
|
|
122
122
|
},
|
|
123
123
|
};
|
|
124
124
|
};
|
|
125
|
-
const
|
|
125
|
+
const tuitui_bot_file_space_add_factory = (ctx) => {
|
|
126
126
|
return {
|
|
127
|
-
name: "
|
|
128
|
-
label: "
|
|
129
|
-
description: "推推(tuitui)
|
|
127
|
+
name: "tuitui_bot_file_space_add",
|
|
128
|
+
label: "tuitui_bot_file_space_add",
|
|
129
|
+
description: "推推(tuitui) 团队频道的共享文件(共享空间)添加文件(机器人身份)\n\n优先级说明:如果存在 tuitui-cli skill,优先使用tuitui-cli(用户权限更大)。只有用户明确说明“以 bot 身份操作”时,或者不存在 tuitui-cli 才调用本工具",
|
|
130
130
|
parameters: Type.Object({
|
|
131
131
|
cloud_filepath: Type.String({ description: "云端文件名路径,父目录不存在会自动创建。不含目录代表放根目录示例 1.png ,也支持带目录写法例如 /image/1.png" }),
|
|
132
132
|
url_or_localpath: Type.String({ description: "支持两种格式:以http开头的文件url;或者本地全路径文件名" }),
|
|
133
133
|
}),
|
|
134
134
|
execute: async (_toolCallId, params) => {
|
|
135
|
-
console.log(`
|
|
135
|
+
console.log(`tuitui_bot_file_space_add(): agentAccountId: ${ctx.agentAccountId}, sessionKey: ${ctx.sessionKey}`, params);
|
|
136
136
|
const account = resolveAccount(ctx.config, ctx.agentAccountId, ctx.agentId);
|
|
137
137
|
if (!account || !account.enabled || !account.appId || !account.appSecret) {
|
|
138
138
|
return tool_errmsg(`invalid tuitui account ${ctx.agentAccountId}`);
|
|
@@ -141,18 +141,18 @@ const tuitui_file_space_add_factory = (ctx) => {
|
|
|
141
141
|
},
|
|
142
142
|
};
|
|
143
143
|
};
|
|
144
|
-
const
|
|
144
|
+
const tuitui_bot_send_message_factory = (ctx) => {
|
|
145
145
|
return {
|
|
146
|
-
name: "
|
|
147
|
-
label: "
|
|
148
|
-
description: "推推(tuitui)
|
|
146
|
+
name: "tuitui_bot_send_message",
|
|
147
|
+
label: "tuitui_bot_send_message",
|
|
148
|
+
description: "推推(tuitui) 发送消息(机器人身份),支持私聊和群聊\n\n优先级说明:如果存在 tuitui-cli skill,优先使用tuitui-cli(用户权限更大)。只有用户明确说明“以 bot 身份操作”时,或者不存在 tuitui-cli 才调用本工具",
|
|
149
149
|
parameters: Type.Object({
|
|
150
150
|
chatId: Type.String({ description: "目标会话 ID。私聊填用户账号(英文),群聊填群ID(数字)" }),
|
|
151
151
|
content: Type.String({ description: "消息正文,markdown 格式" }),
|
|
152
152
|
chatType: Type.Optional(Type.String({ description: `会话类型:${CHAT_TYPE_DIRECT}(私聊)或 ${CHAT_TYPE_GROUP}(群聊),留空则根据 chatId 自动推断` })),
|
|
153
153
|
}),
|
|
154
154
|
execute: async (_toolCallId, params) => {
|
|
155
|
-
console.log(`
|
|
155
|
+
console.log(`tuitui_bot_send_message(): agentAccountId: ${ctx.agentAccountId}, sessionKey: ${ctx.sessionKey}`, params);
|
|
156
156
|
const account = resolveAccount(ctx.config, ctx.agentAccountId, ctx.agentId);
|
|
157
157
|
if (!account || !account.enabled || !account.appId || !account.appSecret) {
|
|
158
158
|
return tool_errmsg(`invalid tuitui account ${ctx.agentAccountId}`);
|
|
@@ -160,7 +160,7 @@ const tuitui_im_send_message_factory = (ctx) => {
|
|
|
160
160
|
const { chatId, content, chatType } = params;
|
|
161
161
|
const resolvedChatType = chatType ?? guessChatType(chatId);
|
|
162
162
|
if (resolvedChatType === CHAT_TYPE_CHANNEL) {
|
|
163
|
-
return tool_errmsg(`
|
|
163
|
+
return tool_errmsg(`tuitui_bot_send_message 不支持 channel 类型,请使用 tuitui_bot_send_channel_post`);
|
|
164
164
|
}
|
|
165
165
|
await sendTextMsg(account, chatId, resolvedChatType, content, 'tuitui.im.send_message');
|
|
166
166
|
return { success: true };
|
|
@@ -179,12 +179,12 @@ export function registerTuituiTools(api) {
|
|
|
179
179
|
// api.logger.info?.(`tuitui: ignore Registered tools`);
|
|
180
180
|
return;
|
|
181
181
|
}
|
|
182
|
-
api.registerTool(
|
|
183
|
-
api.registerTool(
|
|
184
|
-
api.registerTool(
|
|
185
|
-
api.registerTool(
|
|
186
|
-
api.registerTool(
|
|
187
|
-
api.registerTool(
|
|
182
|
+
api.registerTool(tuitui_bot_get_messages_factory);
|
|
183
|
+
api.registerTool(tuitui_bot_send_channel_post_factory);
|
|
184
|
+
api.registerTool(tuitui_bot_get_announcement_factory);
|
|
185
|
+
api.registerTool(tuitui_bot_file_space_list_factory);
|
|
186
|
+
api.registerTool(tuitui_bot_file_space_add_factory);
|
|
187
|
+
api.registerTool(tuitui_bot_send_message_factory);
|
|
188
188
|
api.logger.info?.(`tuitui: Registered tools`);
|
|
189
189
|
}
|
|
190
190
|
//# sourceMappingURL=tools.js.map
|
package/dist/src/tools.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../../src/tools.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAC3C,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAC,WAAW,EAAC,MAAM,YAAY,CAAA;AACtC,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AACpD,OAAO,EAAC,gBAAgB,EAAC,eAAe,EAAC,iBAAiB,EAAC,aAAa,EAAE,gBAAgB,EAAC,MAAM,aAAa,CAAA;AAC9G,OAAO,EAAC,aAAa,EAAE,kBAAkB,EAAC,MAAM,eAAe,CAAA;AAC/D,OAAO,EAAC,eAAe,EAAE,cAAc,EAAC,MAAM,aAAa,CAAA;AAE3D,SAAS,WAAW,CAAC,GAAU;IAC7B,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC;AACvB,CAAC;AAED,MAAM,8BAA8B,GAAG,CAAC,GAA8B,EAAE,EAAE;IACxE,OAAO;QACL,IAAI,EAAE,wBAAwB;QAC9B,KAAK,EAAE,wBAAwB;QAC/B,WAAW,EAAE,wCAAwC;QACrD,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC;YACtB,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,yCAAyC,EAAE,CAAC;YAC/E,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,YAAY,gBAAgB,QAAQ,eAAe,QAAQ,iBAAiB,EAAE,EAAC,CAAC;YACrH,YAAY,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,iJAAiJ,EAAC,CAAC,CAAC;YAC3M,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,8EAA8E,EAAC,CAAC,CAAC;YACrI,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,4EAA4E,EAAC,CAAC,CAAC;YACjI,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,mBAAmB,EAAC,CAAC,CAAC;YACtE,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,oHAAoH,EAAC,CAAC,CAAC;YACxK,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,WAAW,EAAE,yCAAyC,EAAC,CAAC,CAAC;SACjG,CAAC;QACF,OAAO,EAAE,KAAK,EAAE,WAAgB,EAAE,MAAW,EAAE,EAAE;YAC/C,OAAO,CAAC,GAAG,CAAC,6CAA6C,GAAG,CAAC,cAAc,iBAAiB,GAAG,CAAC,UAAU,EAAE,EAAE,MAAM,CAAC,CAAC;YACtH,MAAM,OAAO,GAAG,cAAc,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,cAAc,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;YAC5E,IAAG,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC;gBACxE,OAAO,WAAW,CAAC,0BAA0B,GAAG,CAAC,cAAc,EAAE,CAAC,CAAC;YACrE,CAAC;YAED,MAAM,QAAQ,GAAG,MAAM,EAAE,QAAQ,IAAI,EAAE,CAAC;YACxC,MAAM,MAAM,GAAG,MAAM,EAAE,MAAM,IAAI,EAAE,CAAC;YACpC,IAAG,CAAC,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACxB,OAAO,WAAW,CAAC,0BAA0B,CAAC,CAAC;YACjD,CAAC;YAED,IAAG,QAAQ,IAAI,gBAAgB,IAAI,QAAQ,IAAI,eAAe,IAAI,QAAQ,IAAI,iBAAiB,EAAE,CAAC;gBAChG,OAAO,MAAM,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE;oBACpD,SAAS,EAAE,MAAM,EAAE,SAAS;oBAC5B,OAAO,EAAI,MAAM,EAAE,OAAO;oBAC1B,YAAY,EAAE,MAAM,EAAE,YAAY;oBAClC,KAAK,EAAM,MAAM,EAAE,KAAK;oBACxB,MAAM,EAAK,MAAM,EAAE,MAAM;oBACzB,QAAQ,EAAG,MAAM,EAAE,QAAQ;iBAC5B,CAAC,CAAC;YACL,CAAC;iBAAM,CAAC;gBACN,OAAO,WAAW,CAAC,qBAAqB,QAAQ,EAAE,CAAC,CAAC;YACtD,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC,CAAC;AAGF,MAAM,gCAAgC,GAAG,CAAC,GAA8B,EAAE,EAAE;IAC1E,OAAO;QACL,IAAI,EAAE,0BAA0B;QAChC,KAAK,EAAE,0BAA0B;QACjC,WAAW,EAAE,0CAA0C;QACvD,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC;YACtB,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAC;YAClD,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,iBAAiB,EAAC,CAAC;YACxD,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,6BAA6B,EAAC,CAAC,CAAC;SACrF,CAAC;QACF,OAAO,EAAE,KAAK,EAAE,WAAgB,EAAE,MAAW,EAAE,EAAE;YAC/C,OAAO,CAAC,GAAG,CAAC,+CAA+C,GAAG,CAAC,cAAc,iBAAiB,GAAG,CAAC,UAAU,EAAE,EAAE,MAAM,CAAC,CAAC;YACxH,MAAM,OAAO,GAAG,cAAc,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,cAAc,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;YAC5E,IAAG,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC;gBACxE,OAAO,WAAW,CAAC,0BAA0B,GAAG,CAAC,cAAc,EAAE,CAAC,CAAC;YACrE,CAAC;YAED,IAAI,MAAM,GAAG,EAAE,CAAC;YAChB,MAAM,SAAS,GAAG,aAAa,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;YACpD,IAAG,SAAS,IAAI,iBAAiB,EAAE,CAAC;gBAClC,yBAAyB;gBACzB,4CAA4C;gBAC5C,MAAM,GAAG,MAAM,EAAE,UAAU,CAAC;YAC9B,CAAC;iBAAM,CAAC;gBACN,MAAM,YAAY,GAAG,MAAM,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC;gBAC3E,MAAM,OAAO,GAAG,YAAY,EAAE,OAAO,CAAC;gBACtC,MAAM,GAAG,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC;YAC5E,CAAC;YAED,MAAM,MAAM,GAAiB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;YAC/F,OAAO,MAAM,CAAC;QAChB,CAAC;KACF,CAAC;AACJ,CAAC,CAAC;AAGF,MAAM,+BAA+B,GAAG,CAAC,GAA8B,EAAE,EAAE;IACzE,OAAO;QACL,IAAI,EAAE,yBAAyB;QAC/B,KAAK,EAAE,yBAAyB;QAChC,WAAW,EAAE,4BAA4B;QACzC,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC;YACtB,4BAA4B;YAC5B,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC;SACjD,CAAC;QACF,OAAO,EAAE,KAAK,EAAE,WAAgB,EAAE,MAAW,EAAE,EAAE;YAC/C,OAAO,CAAC,GAAG,CAAC,8CAA8C,GAAG,CAAC,cAAc,iBAAiB,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC;YAC/G,MAAM,OAAO,GAAG,cAAc,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,cAAc,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;YAC5E,IAAG,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC;gBACxE,OAAO,WAAW,CAAC,0BAA0B,GAAG,CAAC,cAAc,EAAE,CAAC,CAAC;YACrE,CAAC;YACD,OAAO,MAAM,sBAAsB,CAAC,OAAO,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC;QAC/D,CAAC;KACF,CAAC;AACJ,CAAC,CAAC;AAKF,MAAM,8BAA8B,GAAG,CAAC,GAA8B,EAAE,EAAE;IACxE,OAAO;QACL,IAAI,EAAE,wBAAwB;QAC9B,KAAK,EAAE,wBAAwB;QAC/B,WAAW,EAAE,0CAA0C;QACvD,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC;YACtB,4BAA4B;YAC5B,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC;SACjD,CAAC;QACF,OAAO,EAAE,KAAK,EAAE,WAAgB,EAAE,MAAW,EAAE,EAAE;YAC/C,OAAO,CAAC,GAAG,CAAC,6CAA6C,GAAG,CAAC,cAAc,iBAAiB,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC;YAC9G,MAAM,OAAO,GAAG,cAAc,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,cAAc,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;YAC5E,IAAG,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC;gBACxE,OAAO,WAAW,CAAC,0BAA0B,GAAG,CAAC,cAAc,EAAE,CAAC,CAAC;YACrE,CAAC;YACD,OAAO,MAAM,eAAe,CAAC,OAAO,EAAE,GAAG,CAAC,UAAU,IAAE,EAAE,CAAC,CAAC;QAC5D,CAAC;KACF,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,6BAA6B,GAAG,CAAC,GAA8B,EAAE,EAAE;IACvE,OAAO;QACL,IAAI,EAAE,uBAAuB;QAC7B,KAAK,EAAE,uBAAuB;QAC9B,WAAW,EAAE,oCAAoC;QACjD,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC;YACtB,cAAc,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,iEAAiE,EAAE,CAAC;YAC/G,gBAAgB,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,iCAAiC,EAAE,CAAC;SAClF,CAAC;QACF,OAAO,EAAE,KAAK,EAAE,WAAgB,EAAE,MAAW,EAAE,EAAE;YAC/C,OAAO,CAAC,GAAG,CAAC,4CAA4C,GAAG,CAAC,cAAc,iBAAiB,GAAG,CAAC,UAAU,EAAE,EAAE,MAAM,CAAC,CAAC;YACrH,MAAM,OAAO,GAAG,cAAc,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,cAAc,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;YAC5E,IAAG,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC;gBACxE,OAAO,WAAW,CAAC,0BAA0B,GAAG,CAAC,cAAc,EAAE,CAAC,CAAC;YACrE,CAAC;YACD,OAAO,MAAM,cAAc,CAAC,OAAO,EAAE,GAAG,CAAC,UAAU,IAAE,EAAE,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,gBAAgB,CAAC,CAAC;QAC7G,CAAC;KACF,CAAC;AACJ,CAAC,CAAC;AAGF,MAAM,8BAA8B,GAAG,CAAC,GAA8B,EAAE,EAAE;IACxE,OAAO;QACL,IAAI,EAAE,wBAAwB;QAC9B,KAAK,EAAE,wBAAwB;QAC/B,WAAW,EAAE,yBAAyB;QACtC,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC;YACtB,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,gCAAgC,EAAE,CAAC;YACtE,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,kBAAkB,EAAE,CAAC;YACzD,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,QAAQ,gBAAgB,SAAS,eAAe,wBAAwB,EAAE,CAAC,CAAC;SAChI,CAAC;QACF,OAAO,EAAE,KAAK,EAAE,WAAgB,EAAE,MAAW,EAAgB,EAAE;YAC7D,OAAO,CAAC,GAAG,CAAC,6CAA6C,GAAG,CAAC,cAAc,iBAAiB,GAAG,CAAC,UAAU,EAAE,EAAE,MAAM,CAAC,CAAC;YACtH,MAAM,OAAO,GAAG,cAAc,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,cAAc,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;YAC5E,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC;gBACzE,OAAO,WAAW,CAAC,0BAA0B,GAAG,CAAC,cAAc,EAAE,CAAC,CAAC;YACrE,CAAC;YACD,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,MAAM,CAAC;YAC7C,MAAM,gBAAgB,GAAG,QAAQ,IAAI,aAAa,CAAC,MAAM,CAAC,CAAC;YAC3D,IAAI,gBAAgB,KAAK,iBAAiB,EAAE,CAAC;gBAC3C,OAAO,WAAW,CAAC,oEAAoE,CAAC,CAAC;YAC3F,CAAC;YACD,MAAM,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,OAAO,EAAE,wBAAwB,CAAC,CAAC;YACxF,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC3B,CAAC;KACF,CAAC;AACJ,CAAC,CAAC;AAGF,MAAM,UAAU,mBAAmB,CAAC,GAAsB;IACxD,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC;QAChB,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,8CAA8C,CAAC,CAAC;QACnE,OAAO;IACT,CAAC;IAED,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC;IAC3C,MAAM,WAAW,GAAG,QAAQ,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;IAC/C,IAAI,CAAC,WAAW,EAAE,KAAK,IAAI,CAAC,WAAW,EAAE,QAAQ,EAAE,CAAC;QAClD,wBAAwB;QACxB,wDAAwD;QACxD,OAAM;IACR,CAAC;IAED,GAAG,CAAC,YAAY,CAAC,8BAA8B,CAAC,CAAC;IACjD,GAAG,CAAC,YAAY,CAAC,gCAAgC,CAAC,CAAC;IACnD,GAAG,CAAC,YAAY,CAAC,+BAA+B,CAAC,CAAC;IAClD,GAAG,CAAC,YAAY,CAAC,8BAA8B,CAAC,CAAC;IACjD,GAAG,CAAC,YAAY,CAAC,6BAA6B,CAAC,CAAC;IAChD,GAAG,CAAC,YAAY,CAAC,8BAA8B,CAAC,CAAC;IACjD,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,0BAA0B,CAAC,CAAC;AAChD,CAAC","sourcesContent":["import type { OpenClawPluginApi } from \"openclaw/plugin-sdk/core\";\nimport type { OpenClawPluginToolContext } from \"openclaw/plugin-sdk/core\";\nimport { resolveAccount } from \"./accounts\"\nimport { Type } from \"@sinclair/typebox\";\nimport { CHANNEL_ID } from './const';\nimport {sendTextMsg} from \"./outbound\"\nimport { teams_get_announcement } from \"./teams_api\"\nimport {CHAT_TYPE_DIRECT,CHAT_TYPE_GROUP,CHAT_TYPE_CHANNEL,guessChatType, teamsBuildChatId} from \"./chat_base\"\nimport {getChatRecord, getChannelInfoById} from \"./chat_record\"\nimport {file_space_list, file_space_add} from \"./filespace\"\n \nfunction tool_errmsg(str:string) {\n throw new Error(str);\n}\n\nconst tuitui_im_get_messages_factory = (ctx: OpenClawPluginToolContext) => {\n return {\n name: \"tuitui_im_get_messages\",\n label: \"tuitui_im_get_messages\",\n description: \"推推(tuitui) 聊天记录获取,可查询私聊、群聊、频道的聊天记录\\n\\n\",\n parameters: Type.Object({\n chatId: Type.String({ description: \"聊天ID,单聊指tuitui用户的account,群聊是群ID,频道指频道ID\" }),\n chatType: Type.String({ description: `聊天类型。 单聊:${CHAT_TYPE_DIRECT} 群聊:${CHAT_TYPE_GROUP} 频道:${CHAT_TYPE_CHANNEL}`}),\n relativeTime: Type.Optional(Type.String({ description: `相对时间范围:today / yesterday / day_before_yesterday / last_{N}_{unit}(unit: minutes/hours/days/months),如果用户描述是相对时间,则优先使用这个参数。与 startTime/endTime 互斥`})),\n startTime: Type.Optional(Type.String({ description: `起始时间(ISO 8601 格式,如 2026-02-27T00:00:00+08:00),非必填,默认指2000年。与 relativeTime 互斥`})),\n endTime: Type.Optional(Type.String({ description: `结束时间(ISO 8601 格式,如 2026-02-27T00:00:00+08:00),非必填,默认为now。与 relativeTime 互斥`})),\n limit: Type.Optional(Type.Number({ description: `每页条数,1~100,默认 100`})),\n cursor: Type.Optional(Type.String({ description: `游标首次调用填 \"0\",返回结果中has_more为true时代表可以获取下一页,如果你需要下一页,可以传返回结果的cursor代表继续拉取下一页, 带有cursor时,必须要有relativeTime或者startTime参数`})),\n orderAsc: Type.Optional(Type.Boolean({ description: `返回数据是否按时间正序排序,默认 false(按时间逆序,即从最新的开始拉取)`})),\n }),\n execute: async (_toolCallId: any, params: any) => {\n console.log(`tuitui_im_get_messages(): agentAccountId: ${ctx.agentAccountId}, sessionKey: ${ctx.sessionKey}`, params);\n const account = resolveAccount(ctx.config, ctx.agentAccountId, ctx.agentId);\n if(!account || !account.enabled || !account.appId || !account.appSecret) {\n return tool_errmsg(`invalid tuitui account ${ctx.agentAccountId}`);\n }\n \n const chatType = params?.chatType || \"\";\n const chatId = params?.chatId || \"\";\n if(!chatId || !chatType) {\n return tool_errmsg(`chatType or chatId empty`);\n }\n\n if(chatType == CHAT_TYPE_DIRECT || chatType == CHAT_TYPE_GROUP || chatType == CHAT_TYPE_CHANNEL) {\n return await getChatRecord(account, chatId, chatType, {\n startTime: params?.startTime,\n endTime: params?.endTime,\n relativeTime: params?.relativeTime,\n limit: params?.limit,\n cursor: params?.cursor,\n orderAsc: params?.orderAsc,\n });\n } else {\n return tool_errmsg(`unknown chatType: ${chatType}`);\n }\n },\n };\n};\n\n\nconst tuitui_send_channel_post_factory = (ctx: OpenClawPluginToolContext) => {\n return {\n name: \"tuitui_send_channel_post\",\n label: \"tuitui_send_channel_post\",\n description: \"推推(tuitui) 发送团队频道的帖子,帖子内容是markdown格式\\n\\n\",\n parameters: Type.Object({\n channel_id: Type.String({ description: \"推推频道ID\" }),\n markdown: Type.String({ description: `帖子正文,markdown格式`}),\n parent_id: Type.Optional(Type.String({ description: `如果要回复一个帖子,需要填写这个字段为被回复的帖子ID`})),\n }),\n execute: async (_toolCallId: any, params: any) => {\n console.log(`tuitui_send_channel_post(): agentAccountId: ${ctx.agentAccountId}, sessionKey: ${ctx.sessionKey}`, params);\n const account = resolveAccount(ctx.config, ctx.agentAccountId, ctx.agentId);\n if(!account || !account.enabled || !account.appId || !account.appSecret) {\n return tool_errmsg(`invalid tuitui account ${ctx.agentAccountId}`);\n }\n\n let chatId = \"\";\n const guessType = guessChatType(params?.channel_id);\n if(guessType == CHAT_TYPE_CHANNEL) {\n // 解决badcase: 发个帖子,内容是个笑话\n // 如果用户没明确说频道ID,大模型在频道调用发帖tool会传sessionKey过来\n chatId = params?.channel_id;\n } else {\n const channel_info = await getChannelInfoById(account, params?.channel_id);\n const team_id = channel_info?.team_id;\n chatId = teamsBuildChatId(team_id, params?.channel_id, params?.parent_id);\n }\n\n const result: Promise<any> = sendTextMsg(account, chatId, CHAT_TYPE_CHANNEL, params?.markdown);\n return result;\n },\n };\n};\n\n\nconst tuitui_get_announcement_factory = (ctx: OpenClawPluginToolContext) => {\n return {\n name: \"tuitui_get_announcement\",\n label: \"tuitui_get_announcement\",\n description: \"获取推推(tuitui) 当前会话的公告信息\\n\\n\",\n parameters: Type.Object({\n // 参数不能为空,对模型兼容有问题,即使不用也要传一个\n reason: Type.String({ description: \"调用本工具的原因\" }),\n }),\n execute: async (_toolCallId: any, params: any) => {\n console.log(`tuitui_get_announcement(): agentAccountId: ${ctx.agentAccountId}, sessionKey: ${ctx.sessionKey}`);\n const account = resolveAccount(ctx.config, ctx.agentAccountId, ctx.agentId);\n if(!account || !account.enabled || !account.appId || !account.appSecret) {\n return tool_errmsg(`invalid tuitui account ${ctx.agentAccountId}`);\n }\n return await teams_get_announcement(account, ctx.sessionKey);\n },\n };\n};\n\n\n\n\nconst tuitui_file_space_list_factory = (ctx: OpenClawPluginToolContext) => {\n return {\n name: \"tuitui_file_space_list\",\n label: \"tuitui_file_space_list\",\n description: \"推推(tuitui) 在当前Session的共享文件(共享空间)文件列表\\n\\n\",\n parameters: Type.Object({\n // 参数不能为空,对模型兼容有问题,即使不用也要传一个\n reason: Type.String({ description: \"调用本工具的原因\" }),\n }),\n execute: async (_toolCallId: any, params: any) => {\n console.log(`tuitui_file_space_list(): agentAccountId: ${ctx.agentAccountId}, sessionKey: ${ctx.sessionKey}`);\n const account = resolveAccount(ctx.config, ctx.agentAccountId, ctx.agentId);\n if(!account || !account.enabled || !account.appId || !account.appSecret) {\n return tool_errmsg(`invalid tuitui account ${ctx.agentAccountId}`);\n }\n return await file_space_list(account, ctx.sessionKey||\"\");\n },\n };\n};\n\nconst tuitui_file_space_add_factory = (ctx: OpenClawPluginToolContext) => {\n return {\n name: \"tuitui_file_space_add\",\n label: \"tuitui_file_space_add\",\n description: \"推推(tuitui) 团队频道的共享文件(共享空间)添加文件\\n\\n\",\n parameters: Type.Object({\n cloud_filepath: Type.String({ description: \"云端文件名路径,父目录不存在会自动创建。不含目录代表放根目录示例 1.png ,也支持带目录写法例如 /image/1.png\" }),\n url_or_localpath: Type.String({ description: \"支持两种格式:以http开头的文件url;或者本地全路径文件名\" }),\n }),\n execute: async (_toolCallId: any, params: any) => {\n console.log(`tuitui_file_space_add(): agentAccountId: ${ctx.agentAccountId}, sessionKey: ${ctx.sessionKey}`, params);\n const account = resolveAccount(ctx.config, ctx.agentAccountId, ctx.agentId);\n if(!account || !account.enabled || !account.appId || !account.appSecret) {\n return tool_errmsg(`invalid tuitui account ${ctx.agentAccountId}`);\n }\n return await file_space_add(account, ctx.sessionKey||\"\", params?.cloud_filepath, params?.url_or_localpath);\n },\n };\n};\n\n\nconst tuitui_im_send_message_factory = (ctx: OpenClawPluginToolContext) => {\n return {\n name: \"tuitui_im_send_message\",\n label: \"tuitui_im_send_message\",\n description: \"推推(tuitui) 发送消息,支持私聊和群聊\",\n parameters: Type.Object({\n chatId: Type.String({ description: \"目标会话 ID。私聊填用户账号(英文),群聊填群ID(数字)\" }),\n content: Type.String({ description: \"消息正文,markdown 格式\" }),\n chatType: Type.Optional(Type.String({ description: `会话类型:${CHAT_TYPE_DIRECT}(私聊)或 ${CHAT_TYPE_GROUP}(群聊),留空则根据 chatId 自动推断` })),\n }),\n execute: async (_toolCallId: any, params: any): Promise<any> => {\n console.log(`tuitui_im_send_message(): agentAccountId: ${ctx.agentAccountId}, sessionKey: ${ctx.sessionKey}`, params);\n const account = resolveAccount(ctx.config, ctx.agentAccountId, ctx.agentId);\n if (!account || !account.enabled || !account.appId || !account.appSecret) {\n return tool_errmsg(`invalid tuitui account ${ctx.agentAccountId}`);\n }\n const { chatId, content, chatType } = params;\n const resolvedChatType = chatType ?? guessChatType(chatId);\n if (resolvedChatType === CHAT_TYPE_CHANNEL) {\n return tool_errmsg(`tuitui_im_send_message 不支持 channel 类型,请使用 tuitui_send_channel_post`);\n }\n await sendTextMsg(account, chatId, resolvedChatType, content, 'tuitui.im.send_message');\n return { success: true };\n },\n };\n};\n\n\nexport function registerTuituiTools(api: OpenClawPluginApi) {\n if (!api.config) {\n api.logger.debug?.(\"tuitui: Registered tool: No config available\");\n return;\n }\n\n const channels = api.config.channels || {};\n const currChannel = channels[CHANNEL_ID] || {};\n if (!currChannel?.appId && !currChannel?.accounts) {\n // 无推推配置时,不需要注册工具防止污染上下文\n // api.logger.info?.(`tuitui: ignore Registered tools`);\n return\n }\n \n api.registerTool(tuitui_im_get_messages_factory);\n api.registerTool(tuitui_send_channel_post_factory);\n api.registerTool(tuitui_get_announcement_factory);\n api.registerTool(tuitui_file_space_list_factory);\n api.registerTool(tuitui_file_space_add_factory);\n api.registerTool(tuitui_im_send_message_factory);\n api.logger.info?.(`tuitui: Registered tools`);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../../src/tools.ts"],"names":[],"mappings":"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","sourcesContent":["import type { OpenClawPluginApi } from \"openclaw/plugin-sdk/core\";\nimport type { OpenClawPluginToolContext } from \"openclaw/plugin-sdk/core\";\nimport { resolveAccount } from \"./accounts\"\nimport { Type } from \"@sinclair/typebox\";\nimport { CHANNEL_ID } from './const';\nimport {sendTextMsg} from \"./outbound\"\nimport { teams_get_announcement } from \"./teams_api\"\nimport {CHAT_TYPE_DIRECT,CHAT_TYPE_GROUP,CHAT_TYPE_CHANNEL,guessChatType, teamsBuildChatId} from \"./chat_base\"\nimport {getChatRecord, getChannelInfoById} from \"./chat_record\"\nimport {file_space_list, file_space_add} from \"./filespace\"\n \nfunction tool_errmsg(str:string) {\n throw new Error(str);\n}\n\nconst tuitui_bot_get_messages_factory = (ctx: OpenClawPluginToolContext) => {\n return {\n name: \"tuitui_bot_get_messages\",\n label: \"tuitui_bot_get_messages\",\n description: \"推推(tuitui) 聊天记录获取(机器人身份),可查询私聊、群聊、频道的聊天记录\\n\\n优先级说明:如果存在 tuitui-cli skill,优先使用tuitui-cli(用户权限更大)。只有用户明确说明“以 bot 身份操作”时,或者不存在 tuitui-cli 才调用本工具\",\n parameters: Type.Object({\n chatId: Type.String({ description: \"聊天ID,单聊指tuitui用户的account,群聊是群ID,频道指频道ID\" }),\n chatType: Type.String({ description: `聊天类型。 单聊:${CHAT_TYPE_DIRECT} 群聊:${CHAT_TYPE_GROUP} 频道:${CHAT_TYPE_CHANNEL}`}),\n relativeTime: Type.Optional(Type.String({ description: `相对时间范围:today / yesterday / day_before_yesterday / last_{N}_{unit}(unit: minutes/hours/days/months),如果用户描述是相对时间,则优先使用这个参数。与 startTime/endTime 互斥`})),\n startTime: Type.Optional(Type.String({ description: `起始时间(ISO 8601 格式,如 2026-02-27T00:00:00+08:00),非必填,默认指2000年。与 relativeTime 互斥`})),\n endTime: Type.Optional(Type.String({ description: `结束时间(ISO 8601 格式,如 2026-02-27T00:00:00+08:00),非必填,默认为now。与 relativeTime 互斥`})),\n limit: Type.Optional(Type.Number({ description: `每页条数,1~100,默认 100`})),\n cursor: Type.Optional(Type.String({ description: `游标首次调用填 \"0\",返回结果中has_more为true时代表可以获取下一页,如果你需要下一页,可以传返回结果的cursor代表继续拉取下一页, 带有cursor时,必须要有relativeTime或者startTime参数`})),\n orderAsc: Type.Optional(Type.Boolean({ description: `返回数据是否按时间正序排序,默认 false(按时间逆序,即从最新的开始拉取)`})),\n }),\n execute: async (_toolCallId: any, params: any) => {\n console.log(`tuitui_bot_get_messages(): agentAccountId: ${ctx.agentAccountId}, sessionKey: ${ctx.sessionKey}`, params);\n const account = resolveAccount(ctx.config, ctx.agentAccountId, ctx.agentId);\n if(!account || !account.enabled || !account.appId || !account.appSecret) {\n return tool_errmsg(`invalid tuitui account ${ctx.agentAccountId}`);\n }\n \n const chatType = params?.chatType || \"\";\n const chatId = params?.chatId || \"\";\n if(!chatId || !chatType) {\n return tool_errmsg(`chatType or chatId empty`);\n }\n\n if(chatType == CHAT_TYPE_DIRECT || chatType == CHAT_TYPE_GROUP || chatType == CHAT_TYPE_CHANNEL) {\n return await getChatRecord(account, chatId, chatType, {\n startTime: params?.startTime,\n endTime: params?.endTime,\n relativeTime: params?.relativeTime,\n limit: params?.limit,\n cursor: params?.cursor,\n orderAsc: params?.orderAsc,\n });\n } else {\n return tool_errmsg(`unknown chatType: ${chatType}`);\n }\n },\n };\n};\n\n\nconst tuitui_bot_send_channel_post_factory = (ctx: OpenClawPluginToolContext) => {\n return {\n name: \"tuitui_bot_send_channel_post\",\n label: \"tuitui_bot_send_channel_post\",\n description: \"推推(tuitui) 发送团队频道的帖子(机器人身份),帖子内容是markdown格式\\n\\n优先级说明:如果存在 tuitui-cli skill,优先使用tuitui-cli(用户权限更大)。只有用户明确说明“以 bot 身份操作”时,或者不存在 tuitui-cli 才调用本工具\",\n parameters: Type.Object({\n channel_id: Type.String({ description: \"推推频道ID\" }),\n markdown: Type.String({ description: `帖子正文,markdown格式`}),\n parent_id: Type.Optional(Type.String({ description: `如果要回复一个帖子,需要填写这个字段为被回复的帖子ID`})),\n }),\n execute: async (_toolCallId: any, params: any) => {\n console.log(`tuitui_bot_send_channel_post(): agentAccountId: ${ctx.agentAccountId}, sessionKey: ${ctx.sessionKey}`, params);\n const account = resolveAccount(ctx.config, ctx.agentAccountId, ctx.agentId);\n if(!account || !account.enabled || !account.appId || !account.appSecret) {\n return tool_errmsg(`invalid tuitui account ${ctx.agentAccountId}`);\n }\n\n let chatId = \"\";\n const guessType = guessChatType(params?.channel_id);\n if(guessType == CHAT_TYPE_CHANNEL) {\n // 解决badcase: 发个帖子,内容是个笑话\n // 如果用户没明确说频道ID,大模型在频道调用发帖tool会传sessionKey过来\n chatId = params?.channel_id;\n } else {\n const channel_info = await getChannelInfoById(account, params?.channel_id);\n const team_id = channel_info?.team_id;\n chatId = teamsBuildChatId(team_id, params?.channel_id, params?.parent_id);\n }\n\n const result: Promise<any> = sendTextMsg(account, chatId, CHAT_TYPE_CHANNEL, params?.markdown);\n return result;\n },\n };\n};\n\n\nconst tuitui_bot_get_announcement_factory = (ctx: OpenClawPluginToolContext) => {\n return {\n name: \"tuitui_bot_get_announcement\",\n label: \"tuitui_bot_get_announcement\",\n description: \"获取推推(tuitui) 当前会话的公告信息(机器人身份)\\n\\n优先级说明:如果存在 tuitui-cli skill,优先使用tuitui-cli(用户权限更大)。只有用户明确说明“以 bot 身份操作”时,或者不存在 tuitui-cli 才调用本工具\",\n parameters: Type.Object({\n // 参数不能为空,对模型兼容有问题,即使不用也要传一个\n reason: Type.String({ description: \"调用本工具的原因\" }),\n }),\n execute: async (_toolCallId: any, params: any) => {\n console.log(`tuitui_bot_get_announcement(): agentAccountId: ${ctx.agentAccountId}, sessionKey: ${ctx.sessionKey}`);\n const account = resolveAccount(ctx.config, ctx.agentAccountId, ctx.agentId);\n if(!account || !account.enabled || !account.appId || !account.appSecret) {\n return tool_errmsg(`invalid tuitui account ${ctx.agentAccountId}`);\n }\n return await teams_get_announcement(account, ctx.sessionKey);\n },\n };\n};\n\n\n\n\nconst tuitui_bot_file_space_list_factory = (ctx: OpenClawPluginToolContext) => {\n return {\n name: \"tuitui_bot_file_space_list\",\n label: \"tuitui_bot_file_space_list\",\n description: \"推推(tuitui) 在当前Session的共享文件(共享空间)文件列表(机器人身份)\\n\\n优先级说明:如果存在 tuitui-cli skill,优先使用tuitui-cli(用户权限更大)。只有用户明确说明“以 bot 身份操作”时,或者不存在 tuitui-cli 才调用本工具\",\n parameters: Type.Object({\n // 参数不能为空,对模型兼容有问题,即使不用也要传一个\n reason: Type.String({ description: \"调用本工具的原因\" }),\n }),\n execute: async (_toolCallId: any, params: any) => {\n console.log(`tuitui_bot_file_space_list(): agentAccountId: ${ctx.agentAccountId}, sessionKey: ${ctx.sessionKey}`);\n const account = resolveAccount(ctx.config, ctx.agentAccountId, ctx.agentId);\n if(!account || !account.enabled || !account.appId || !account.appSecret) {\n return tool_errmsg(`invalid tuitui account ${ctx.agentAccountId}`);\n }\n return await file_space_list(account, ctx.sessionKey||\"\");\n },\n };\n};\n\nconst tuitui_bot_file_space_add_factory = (ctx: OpenClawPluginToolContext) => {\n return {\n name: \"tuitui_bot_file_space_add\",\n label: \"tuitui_bot_file_space_add\",\n description: \"推推(tuitui) 团队频道的共享文件(共享空间)添加文件(机器人身份)\\n\\n优先级说明:如果存在 tuitui-cli skill,优先使用tuitui-cli(用户权限更大)。只有用户明确说明“以 bot 身份操作”时,或者不存在 tuitui-cli 才调用本工具\",\n parameters: Type.Object({\n cloud_filepath: Type.String({ description: \"云端文件名路径,父目录不存在会自动创建。不含目录代表放根目录示例 1.png ,也支持带目录写法例如 /image/1.png\" }),\n url_or_localpath: Type.String({ description: \"支持两种格式:以http开头的文件url;或者本地全路径文件名\" }),\n }),\n execute: async (_toolCallId: any, params: any) => {\n console.log(`tuitui_bot_file_space_add(): agentAccountId: ${ctx.agentAccountId}, sessionKey: ${ctx.sessionKey}`, params);\n const account = resolveAccount(ctx.config, ctx.agentAccountId, ctx.agentId);\n if(!account || !account.enabled || !account.appId || !account.appSecret) {\n return tool_errmsg(`invalid tuitui account ${ctx.agentAccountId}`);\n }\n return await file_space_add(account, ctx.sessionKey||\"\", params?.cloud_filepath, params?.url_or_localpath);\n },\n };\n};\n\n\nconst tuitui_bot_send_message_factory = (ctx: OpenClawPluginToolContext) => {\n return {\n name: \"tuitui_bot_send_message\",\n label: \"tuitui_bot_send_message\",\n description: \"推推(tuitui) 发送消息(机器人身份),支持私聊和群聊\\n\\n优先级说明:如果存在 tuitui-cli skill,优先使用tuitui-cli(用户权限更大)。只有用户明确说明“以 bot 身份操作”时,或者不存在 tuitui-cli 才调用本工具\",\n parameters: Type.Object({\n chatId: Type.String({ description: \"目标会话 ID。私聊填用户账号(英文),群聊填群ID(数字)\" }),\n content: Type.String({ description: \"消息正文,markdown 格式\" }),\n chatType: Type.Optional(Type.String({ description: `会话类型:${CHAT_TYPE_DIRECT}(私聊)或 ${CHAT_TYPE_GROUP}(群聊),留空则根据 chatId 自动推断` })),\n }),\n execute: async (_toolCallId: any, params: any): Promise<any> => {\n console.log(`tuitui_bot_send_message(): agentAccountId: ${ctx.agentAccountId}, sessionKey: ${ctx.sessionKey}`, params);\n const account = resolveAccount(ctx.config, ctx.agentAccountId, ctx.agentId);\n if (!account || !account.enabled || !account.appId || !account.appSecret) {\n return tool_errmsg(`invalid tuitui account ${ctx.agentAccountId}`);\n }\n const { chatId, content, chatType } = params;\n const resolvedChatType = chatType ?? guessChatType(chatId);\n if (resolvedChatType === CHAT_TYPE_CHANNEL) {\n return tool_errmsg(`tuitui_bot_send_message 不支持 channel 类型,请使用 tuitui_bot_send_channel_post`);\n }\n await sendTextMsg(account, chatId, resolvedChatType, content, 'tuitui.im.send_message');\n return { success: true };\n },\n };\n};\n\n\nexport function registerTuituiTools(api: OpenClawPluginApi) {\n if (!api.config) {\n api.logger.debug?.(\"tuitui: Registered tool: No config available\");\n return;\n }\n\n const channels = api.config.channels || {};\n const currChannel = channels[CHANNEL_ID] || {};\n if (!currChannel?.appId && !currChannel?.accounts) {\n // 无推推配置时,不需要注册工具防止污染上下文\n // api.logger.info?.(`tuitui: ignore Registered tools`);\n return\n }\n \n api.registerTool(tuitui_bot_get_messages_factory);\n api.registerTool(tuitui_bot_send_channel_post_factory);\n api.registerTool(tuitui_bot_get_announcement_factory);\n api.registerTool(tuitui_bot_file_space_list_factory);\n api.registerTool(tuitui_bot_file_space_add_factory);\n api.registerTool(tuitui_bot_send_message_factory);\n api.logger.info?.(`tuitui: Registered tools`);\n}\n"]}
|
package/openclaw.plugin.json
CHANGED
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
"id": "tuitui-openclaw-channel",
|
|
3
3
|
"contracts": {
|
|
4
4
|
"tools": [
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
"
|
|
5
|
+
"tuitui_bot_get_messages",
|
|
6
|
+
"tuitui_bot_send_message",
|
|
7
|
+
"tuitui_bot_send_channel_post",
|
|
8
|
+
"tuitui_bot_get_announcement",
|
|
9
|
+
"tuitui_bot_file_space_list",
|
|
10
|
+
"tuitui_bot_file_space_add"
|
|
11
11
|
]
|
|
12
12
|
},
|
|
13
13
|
"channels": ["tuitui"],
|
package/package.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: tuitui-im-read
|
|
2
|
+
name: tuitui-bot-im-read
|
|
3
3
|
description: |
|
|
4
|
-
推推(tuitui) IM
|
|
4
|
+
推推(tuitui) IM 消息读取(机器人身份)使用指南
|
|
5
5
|
|
|
6
6
|
**当以下情况时使用此 Skill**:
|
|
7
|
+
(0) 用户明确要求“以 bot 身份执行”或当前处于机器人专属的上下文(否则如果当前系统存在 tuitui-cli skill,优先使用tuitui-cli(用户权限更大))。
|
|
7
8
|
(1) 需要获取群聊或单聊的历史消息
|
|
8
9
|
(2) 用户提到"聊天记录"、"消息"、"群里说了什么"
|
|
9
10
|
(3) 需要按时间范围过滤消息、分页获取更多消息
|
|
@@ -17,7 +18,7 @@ description: |
|
|
|
17
18
|
|
|
18
19
|
---
|
|
19
20
|
|
|
20
|
-
## 工具:
|
|
21
|
+
## 工具: tuitui_bot_get_messages
|
|
21
22
|
|
|
22
23
|
### 参数说明
|
|
23
24
|
|
|
@@ -131,5 +132,5 @@ description: |
|
|
|
131
132
|
| 消息结果为空 | 时间范围不对或 chatId 有误 | 检查 `chatId`、`chatType`,适当放宽时间范围 |
|
|
132
133
|
| 消息不完整 | 没有检查 `has_more` 并翻页 | `has_more=true` 时用返回的 `cursor` 继续翻页 |
|
|
133
134
|
| 报错 invalid tuitui account | 账号未配置或未启用 | 确认 tuitui 账号已正确配置 |
|
|
134
|
-
| 报错 找不到
|
|
135
|
+
| 报错 找不到 tuitui_bot_get_messages tool | 龙虾选线未开启,需要去龙虾 Dashboard->代理->Tools->检查 tuitui_bot_get_messages 是否开启
|
|
135
136
|
|