Skip to content

Feishu: reply to topic roots#29968

Merged
Takhoffman merged 2 commits intoopenclaw:mainfrom
bmendonca3:bm/feishu-topic-root-reply
Mar 2, 2026
Merged

Feishu: reply to topic roots#29968
Takhoffman merged 2 commits intoopenclaw:mainfrom
bmendonca3:bm/feishu-topic-root-reply

Conversation

@bmendonca3
Copy link

Summary

Describe the problem and fix in 2–5 bullets:

  • Problem: Feishu bot replies inside topic groups pass the child message_id into the reply dispatcher instead of the topic root_id.
  • Why it matters: Feishu treats that child-target reply as a new topic, so the bot fragments the conversation instead of staying under the original topic.
  • What changed: the Feishu bot now resolves the reply target as ctx.rootId ?? ctx.messageId, and the bot test suite now covers existing-topic replies explicitly.
  • What did NOT change (scope boundary): no session-routing changes, no outbound rendering changes, and no non-topic Feishu reply behavior.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

User-visible / Behavior Changes

Feishu bot replies in existing topic-group threads now stay under the original topic instead of opening a new standalone topic.

Security Impact (required)

  • New permissions/capabilities? (No)
  • Secrets/tokens handling changed? (No)
  • New/changed network calls? (No)
  • Command/tool execution surface changed? (No)
  • Data access scope changed? (No)
  • If any Yes, explain risk + mitigation:

Repro + Verification

Environment

  • OS: macOS 26.1
  • Runtime/container: local checkout
  • Model/provider: N/A
  • Integration/channel (if any): Feishu extension
  • Relevant config (redacted): channels.feishu.groups.oc-group.replyInThread: "enabled"

Steps

  1. Configure Feishu group replies with replyInThread: "enabled".
  2. Send the bot a message inside an existing Feishu topic where the inbound event contains both message_id and root_id.
  3. Inspect the createFeishuReplyDispatcher(...) call from handleFeishuMessage(...).

Expected

  • The dispatcher should reply to the topic root message ID.

Actual

  • On upstream/main, the dispatcher receives the child message_id, which causes Feishu to create a new topic instead of replying under the existing one.

Evidence

Attach at least one:

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

What you personally verified (not just CI), and how:

  • Verified scenarios: reproduced the failure locally with a focused temporary Vitest case that expected replyToMessageId: "om_root_topic", then confirmed the same case passes after the fix.
  • Edge cases checked: non-topic replies still fall back to ctx.messageId, and topic session routing remains unchanged.
  • What you did not verify: live Feishu traffic against a production tenant.

Compatibility / Migration

  • Backward compatible? (Yes)
  • Config/env changes? (No)
  • Migration needed? (No)
  • If yes, exact upgrade steps:

Failure Recovery (if this breaks)

  • How to disable/revert this change quickly: revert this commit to restore the previous reply-target behavior.
  • Files/config to restore: extensions/feishu/src/bot.ts, extensions/feishu/src/bot.test.ts
  • Known bad symptoms reviewers should watch for: replies in existing topic threads landing under the wrong topic root.

Risks and Mitigations

  • Risk: topic-group replies now prefer root_id whenever Feishu supplies one.
    • Mitigation: Feishu only includes root_id for topic-thread messages, and the code still falls back to message_id for every non-topic path.

Verification Commands

pnpm exec vitest run extensions/feishu/src/bot.test.ts --config /tmp/vitest.single-feishu-bot.config.ts
pnpm exec vitest run /tmp/feishu-topic-root-repro.test.ts --config /tmp/vitest.single-topic-repro.config.ts
pnpm check

pnpm check still fails on current upstream/main because of unrelated baseline typecheck errors in extensions/diagnostics-otel/src/service.ts, src/discord/voice/manager.ts, src/gateway/server-cron.ts, and src/shared/net/ip.ts.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 932d0289c9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

...mediaPayload,
});

const replyTargetMessageId = ctx.rootId ?? ctx.messageId;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Restrict root-id reply targeting to thread mode

handleFeishuMessage now always prefers ctx.rootId for replyToMessageId, but sendMessageFeishu only sets reply_in_thread when replyInThread is enabled. In groups where replyInThread is disabled, any inbound event carrying root_id will therefore be replied to as a normal inline reply against the topic root (older message) instead of the triggering message, which changes reply anchoring behavior outside the intended thread-mode fix.

Useful? React with 👍 / 👎.

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Feb 28, 2026

Greptile Summary

This PR fixes a Feishu bot bug where replies inside existing topic groups were creating new standalone topics instead of staying within the original thread. The fix changes the reply target from always using the child message_id to preferring the topic root_id when available (ctx.rootId ?? ctx.messageId).

Key Changes:

  • Modified bot.ts to use ctx.rootId ?? ctx.messageId as the reply target instead of just ctx.messageId
  • Added test coverage for topic replies with explicit verification of replyToMessageId: "om_root_topic"
  • Updated CHANGELOG with clear description of the fix

Impact:

  • Topic replies now correctly target the root message, keeping conversations threaded
  • Non-topic messages continue to work as before (backward compatible)
  • Typing indicators and reply metadata now reference the correct message

Confidence Score: 5/5

  • This PR is safe to merge with minimal risk
  • The change is a focused one-line fix with proper test coverage and no security implications. The logic correctly uses nullish coalescing to prefer root_id when present while maintaining backward compatibility. All other usages of message_id remain appropriately unchanged.
  • No files require special attention

Last reviewed commit: 932d028

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d501f8ba6d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

...mediaPayload,
});

const replyTargetMessageId = ctx.rootId ?? ctx.messageId;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Gate root-id reply targeting behind thread mode

replyTargetMessageId now always prefers ctx.rootId, but sendMessageFeishu only adds reply_in_thread when replyInThread is enabled; when thread mode is disabled and an inbound group message still carries root_id, replies are sent as normal inline replies to the topic root instead of the triggering message, which changes anchoring behavior outside the intended thread-mode fix.

Useful? React with 👍 / 👎.

@Takhoffman Takhoffman force-pushed the bm/feishu-topic-root-reply branch from d501f8b to 67dac11 Compare March 2, 2026 23:41
@Takhoffman Takhoffman merged commit 1234cc4 into openclaw:main Mar 2, 2026
1 check passed
@Takhoffman
Copy link
Contributor

Merged via autoland after rebase conflict resolution with #29788 semantics preserved.

Verification run:

  • pnpm install --frozen-lockfile
  • pnpm test -- extensions/feishu/src/bot.test.ts
  • pnpm build

Changelog:

Merge commit: 1234cc4

dawi369 pushed a commit to dawi369/davis that referenced this pull request Mar 3, 2026
* Feishu: reply to topic roots

* Changelog: note Feishu topic-root reply targeting

---------

Co-authored-by: bmendonca3 <208517100+bmendonca3@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
guoqunabc added a commit to guoqunabc/openclaw that referenced this pull request Mar 4, 2026
Add a new `replyTarget` config option (`"message"" | "root"`, default
`"message"`) for Feishu group chats to control whether bot replies target
the triggering message or the topic root message.

PR openclaw#29968 changed the reply target from `ctx.messageId` to
`ctx.rootId ?? ctx.messageId`. While this works well for groups with
topic mode enabled, it causes a regression in normal group chats:
when a user quote-replies to @bot, Feishu attaches a `root_id` to the
message, causing the bot's reply to silently enter a topic thread
instead of appearing in the main chat view.

This adds a configurable option so users can choose the appropriate
behavior for their group type:
- "message" (default): reply to the triggering message (pre-openclaw#29968)
- "root": reply to the topic root (post-openclaw#29968 behavior)

The config can be set per-group or globally in the feishu channel config.
OWALabuy pushed a commit to kcinzgg/openclaw that referenced this pull request Mar 4, 2026
* Feishu: reply to topic roots

* Changelog: note Feishu topic-root reply targeting

---------

Co-authored-by: bmendonca3 <208517100+bmendonca3@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
zooqueen pushed a commit to hanzoai/bot that referenced this pull request Mar 6, 2026
* Feishu: reply to topic roots

* Changelog: note Feishu topic-root reply targeting

---------

Co-authored-by: bmendonca3 <208517100+bmendonca3@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: feishu Channel integration: feishu size: XS

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[feishu] Bot replies create new topics instead of replying under the original topic in topic groups

2 participants