claw-lark Patches
claw-lark is a compiled plugin — we patch dist files directly. Every plugin update wipes these patches. This skill documents exactly what to change and provides an auto-apply script.
Quick Apply
CODEBLOCK0
Then restart gateway: INLINECODE0
Patches Overview
Four files are patched:
- 1. channel.js — messaging.targetResolver (target ID recognition) + outbound account resolution
- monitor.js — requireMention filtering + reply-in-thread for deliver callback
- provider.js — reply-in-thread for sendTextMessage
- send.js — reply-in-thread for SDK reply calls
Patch Details
0. channel.js — Target Resolution + Account Resolution (2026-02-22)
Problem 1: message(send, lark, "oc_xxx") returns "Unknown target" because claw-lark has no messaging.targetResolver.looksLikeId. The core doesn't recognize oc_/ou_/on_ as valid IDs and falls through to directory lookup which fails.
Fix: Add messaging property to larkPlugin export:
- - Import
looksLikeLarkId, normalizeLarkTarget from INLINECODE7 - Add
messaging.targetResolver.looksLikeId using existing INLINECODE9 - Add
messaging.normalizeTarget using existing INLINECODE11
Problem 2: outbound.sendText gets { cfg, to, accountId } from core but expects { account, recipientId }. The account object is undefined → "Cannot read properties of undefined (reading 'appId')".
Fix: All 5 outbound methods (sendText, sendMedia, downloadMedia, addReaction, removeReaction) add:
CODEBLOCK1
1. monitor.js — requireMention Filter
Location: routeMessage() function, after parseMessage(event) and the log line.
What: In group chats, skip messages that don't @mention our bot.
Key facts:
- -
event.message is the correct path (NOT event.event.message) - Lark webhook
message.mentions contains mention data with INLINECODE26 - Bot open_id: set via
BOT_OPEN_ID env var when running INLINECODE28 - All bots lack
user_id (empty string) — cannot use !user_id to detect "is it me" - INLINECODE31 text placeholders appear for ALL @'d bots, not just ours — don't use regex match
- Fallback: if mentions array empty, check
parsed.text.includes("@" + BOT_NAME) (set via BOT_NAME env var)
2. monitor.js — Reply in Thread (deliver callback)
Location: Inside dispatchReplyWithBufferedBlockDispatcher deliver callback.
What:
- - Set
replyToId = payload.replyToId || parsed.threadId || parsed.messageId (always have a value) - Use
client.im.message.reply() with reply_in_thread: true instead of client.im.message.create() with INLINECODE39
Key facts:
- -
root_id on create only associates with existing thread, does NOT create new thread - INLINECODE41 on reply API creates a new thread
- Works in both p2p and group chats
3. provider.js — sendTextMessage Thread Reply
Location: sendTextMessage() function.
What: When threadId is provided, use client.im.message.reply() instead of client.im.message.create().
4. send.js — replyinthread on SDK Reply
Location: sendMessageLark() and sendCardLark() reply branches.
What: Add reply_in_thread: true to data object in client.im.message.reply() calls.
Verification
After applying patches and restarting gateway:
- 1. Send a group message WITHOUT @bot → should be silently ignored
- Send a group message WITH @bot → should reply in thread
- Send a DM → should reply in thread
- @ another bot → should be silently ignored
See Also
- -
references/patch-details.md — Full code diffs for each patch
claw-lark 补丁
claw-lark 是一个编译型插件——我们直接修补分发文件。每次插件更新都会清除这些补丁。 本技能详细记录了需要修改的内容,并提供了自动应用脚本。
快速应用
bash
bash scripts/apply-patches.sh
然后重启网关:openclaw gateway restart
补丁概览
四个文件需要修补:
- 1. channel.js — messaging.targetResolver(目标ID识别)+ 出站账户解析
- monitor.js — requireMention 过滤 + 回复到线程(用于 deliver 回调)
- provider.js — 回复到线程(用于 sendTextMessage)
- send.js — 回复到线程(用于 SDK 回复调用)
补丁详情
0. channel.js — 目标解析 + 账户解析(2026-02-22)
问题1:message(send, lark, ocxxx) 返回未知目标,因为 claw-lark 没有 messaging.targetResolver.looksLikeId。核心无法识别 oc/ou/on 为有效ID,转而执行目录查找并失败。
修复:为 larkPlugin 导出添加 messaging 属性:
- - 从 ./utils.js 导入 looksLikeLarkId, normalizeLarkTarget
- 使用现有的 looksLikeLarkId() 添加 messaging.targetResolver.looksLikeId
- 使用现有的 normalizeLarkTarget() 添加 messaging.normalizeTarget
问题2:outbound.sendText 从核心接收 { cfg, to, accountId },但期望 { account, recipientId }。account 对象未定义 → 无法读取未定义属性(读取appId)。
修复:所有5个出站方法(sendText、sendMedia、downloadMedia、addReaction、removeReaction)添加:
javascript
const account = args.account ?? resolveAccount(args.cfg, args.accountId ?? default);
const recipientId = args.recipientId ?? args.to;
1. monitor.js — requireMention 过滤
位置:routeMessage() 函数中,在 parseMessage(event) 和日志行之后。
功能:在群聊中,跳过未@提及我们机器人的消息。
关键事实:
- - event.message 是正确的路径(不是 event.event.message)
- Lark webhook message.mentions 包含提及数据,带有 id.openid
- 机器人 openid:运行 apply-patches.sh 时通过 BOTOPENID 环境变量设置
- 所有机器人缺少 userid(空字符串)——无法使用 !userid 检测是否是我
- @userN 文本占位符出现在所有被@的机器人中,不仅限于我们的——不要使用正则匹配
- 回退方案:如果提及数组为空,检查 parsed.text.includes(@ + BOTNAME)(通过 BOTNAME 环境变量设置)
2. monitor.js — 回复到线程(deliver 回调)
位置:在 dispatchReplyWithBufferedBlockDispatcher 的 deliver 回调内部。
功能:
- - 设置 replyToId = payload.replyToId || parsed.threadId || parsed.messageId(始终有值)
- 使用 client.im.message.reply() 并设置 replyinthread: true,替代使用 root_id 的 client.im.message.create()
关键事实:
- - create 上的 rootid 仅关联现有线程,不会创建新线程
- reply API 上的 replyin_thread: true 会创建新线程
- 在私聊和群聊中均有效
3. provider.js — sendTextMessage 线程回复
位置:sendTextMessage() 函数。
功能:当提供 threadId 时,使用 client.im.message.reply() 替代 client.im.message.create()。
4. send.js — SDK 回复中的 replyinthread
位置:sendMessageLark() 和 sendCardLark() 的回复分支。
功能:在 client.im.message.reply() 调用的数据对象中添加 replyinthread: true。
验证
应用补丁并重启网关后:
- 1. 发送一条未@机器人的群消息 → 应被静默忽略
- 发送一条@机器人的群消息 → 应在线程中回复
- 发送一条私聊消息 → 应在线程中回复
- @其他机器人 → 应被静默忽略
参见
- - references/patch-details.md — 每个补丁的完整代码差异