Skip to content

fix(feishu): reply inside thread for P2P direct messages#38808

Closed
LiaoyuanNing wants to merge 3 commits intoopenclaw:mainfrom
LiaoyuanNing:fix/feishu-p2p-thread-reply
Closed

fix(feishu): reply inside thread for P2P direct messages#38808
LiaoyuanNing wants to merge 3 commits intoopenclaw:mainfrom
LiaoyuanNing:fix/feishu-p2p-thread-reply

Conversation

@LiaoyuanNing
Copy link
Copy Markdown
Contributor

Summary

  • Fix bot replying outside thread in P2P (direct message) chats when user sends a message inside a Feishu thread
  • Distinguish between thread messages (thread_id present) and plain quote replies (root_id only) per the Feishu API contract
  • Group chat behavior is completely unchanged — the new condition requires isDirect=true

Fixes #38806

Changes

Four targeted changes in extensions/feishu/src/bot.ts, all gated by directThreadMessage = isDirect && Boolean(ctx.threadId):

Parameter Before (P2P) After (P2P thread) After (P2P non-thread)
replyInThread false true false (unchanged)
replyTargetMessageId ctx.messageId ctx.rootId ctx.messageId (unchanged)
threadReply false true false (unchanged)
skipReplyToInMessages true false true (unchanged)

Test plan

  • Added test: P2P thread message (thread_id present) → replies to root with replyInThread=true
  • Added test: P2P plain reply (root_id only, no thread_id) → replies to triggering message with replyInThread=false
  • All 54 existing feishu bot tests pass
  • Manual verification: send message in P2P thread, confirm bot replies inside thread

@openclaw-barnacle openclaw-barnacle Bot added channel: feishu Channel integration: feishu size: S labels Mar 7, 2026
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Mar 7, 2026

Greptile Summary

This PR fixes a Feishu bot regression where replies to P2P (direct message) thread messages were posted outside the thread container. The fix introduces a directThreadMessage flag (isDirect && Boolean(ctx.threadId)) to distinguish Feishu thread messages from plain quote replies in P2P chats, and uses it to correctly set replyInThread, threadReply, replyTargetMessageId, and skipReplyToInMessages — only for the thread case.

The directThreadMessage guard is correctly scoped to isDirect, so group chat behavior is completely unaffected. Both broadcast and non-broadcast dispatcher call sites are updated consistently. The fallback ctx.rootId ?? ctx.messageId gracefully handles any edge case where rootId is absent despite threadId being present. Two new tests cover the P2P-thread and P2P-plain-reply paths with precise assertions; no existing tests were modified.

Confidence Score: 5/5

  • This PR is safe to merge — the change is minimal, well-guarded by an isDirect condition, and covered by two new targeted tests.
  • The fix is narrow (four lines of logic under a single boolean flag), does not affect group chats at all, preserves the existing P2P non-thread behavior exactly, and is backed by two new tests that assert the correct parameters for each case. No risky patterns such as removed validations, new async paths, or external API contract changes were introduced.
  • No files require special attention.

Last reviewed commit: 1bd3555

@LiaoyuanNing
Copy link
Copy Markdown
Contributor Author

Hi @steipete @onutc, this is a small fix for Feishu P2P thread replies. Greptile bot confirmed it's safe to merge. Could you take a look when you have a chance? Thanks!

@openclaw-barnacle
Copy link
Copy Markdown

This pull request has been automatically marked as stale due to inactivity.
Please add updates or it will be closed.

@openclaw-barnacle openclaw-barnacle Bot added the stale Marked as stale due to inactivity label Apr 22, 2026
@clawsweeper
Copy link
Copy Markdown
Contributor

clawsweeper Bot commented Apr 26, 2026

Codex review: keeping this open for maintainer follow-up; there is still a little grit to resolve.

Keep this PR open. Current main still routes Feishu P2P direct-thread messages through the non-thread DM path, while the paired open bug #38806 remains unresolved and this PR is the active narrow implementation candidate. The provided PR diff is scoped to Feishu bot routing, tests, and changelog, with no visible security-sensitive or supply-chain changes.

Best possible solution:

Review and land this narrow Feishu plugin fix, or apply the same behavior on main: detect direct messages with thread_id, reply to root_id with replyInThread/threadReply enabled, keep root_id-only P2P quote replies on the non-thread path, preserve existing group behavior, and keep focused regression tests. After merge, close #38806 as implemented.

What I checked:

  • current-main-p2p-reply-in-thread-missing: Current main still sets replyInThread to false for every non-group Feishu message, so a P2P event with thread_id cannot request Feishu reply_in_thread through this path. (extensions/feishu/src/bot.ts:704, ef58307f843e)
  • current-main-reply-target-and-thread-reply-group-gated: The reply target chooses a root only for topic/configured group sessions, and threadReply is still false for non-groups, leaving P2P thread messages outside the thread-aware branch. (extensions/feishu/src/bot.ts:1214, ef58307f843e)
  • current-main-dispatch-skips-p2p-reply-metadata: Both dispatcher call sites still pass skipReplyToInMessages: !isGroup; in direct chats the reply dispatcher drops replyToMessageId, so the send layer cannot use im.message.reply for P2P thread replies. (extensions/feishu/src/bot.ts:1279, ef58307f843e)
  • send-layer-already-supports-thread-reply: The Feishu send helper already calls client.im.message.reply and includes reply_in_thread: true when replyInThread is passed; the missing piece is the bot routing decision targeted by this PR. (extensions/feishu/src/send.ts:161, ef58307f843e)
  • current-test-gap: Current tests cover group thread forcing and many P2P paths, but the searched current tree has no P2P thread_id regression test like the one proposed by the PR. (extensions/feishu/src/bot.test.ts:2644, ef58307f843e)
  • pr-diff-security-review: Provided PR file context shows changes only to CHANGELOG.md, extensions/feishu/src/bot.ts, and extensions/feishu/src/bot.test.ts; it does not touch CI workflows, lockfiles, package metadata, install/build scripts, dependencies, downloaded artifacts, or secret-handling code. (e0a0ba6ce823)

Likely related people:

Remaining risk / open question:

Codex review notes: model gpt-5.5, reasoning high; reviewed against ef58307f843e.

@vincentkoc
Copy link
Copy Markdown
Member

ProjectClownfish pushed a narrow repair to this branch so the original contributor path can stay canonical.

Source PR: #38808
Validation: pnpm check:changed
Contributor credit is preserved in the branch history and PR context.

LiaoyuanNing and others added 3 commits April 28, 2026 18:23
When a user sends a message inside a Feishu thread (话题) in a P2P
chat, the bot's reply was incorrectly sent outside the thread as a
standalone message. This was caused by PR openclaw#33789 which fixed group
reply targeting (openclaw#32980) but inadvertently broke P2P thread replies
by gating all thread-aware logic behind isGroup checks.

The fix distinguishes between two P2P scenarios based on the Feishu
API contract (thread_id present = thread message, root_id only =
quote reply):

- P2P thread messages (thread_id present): reply to root_id with
  reply_in_thread=true so the response stays in the thread.
- P2P plain replies (root_id only, no thread_id): reply to the
  triggering message as before.

Group chat behavior is completely unchanged — the new condition
(directThreadMessage) requires isDirect=true, which is always false
for groups.

Changes:
- replyInThread: true for P2P thread messages (enables reply_in_thread API flag)
- replyTargetMessageId: use root_id for P2P thread messages
- threadReply: true for P2P thread messages (drives effectiveReplyInThread in dispatcher)
- skipReplyToInMessages: false for P2P thread messages (so send layer
  uses im.message.reply instead of im.message.create)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@vincentkoc vincentkoc force-pushed the fix/feishu-p2p-thread-reply branch from 84d0830 to e0a0ba6 Compare April 28, 2026 18:28
@vincentkoc
Copy link
Copy Markdown
Member

ProjectClownfish pushed a narrow repair to this branch so the original contributor path can stay canonical.

Source PR: #38808
Validation: pnpm check:changed
Contributor credit is preserved in the branch history and PR context.

@openclaw-clownfish
Copy link
Copy Markdown
Contributor

ProjectClownfish could not safely update this branch, so it opened a narrow replacement PR instead.

Replacement PR: #73972
Source PR: #38808
Contributor credit is preserved in the replacement PR body and changelog plan.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: feishu Channel integration: feishu clawsweeper Tracked by ClawSweeper automation size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: bot replies outside thread in P2P direct message thread

2 participants