Skip to content

[Feature]: Feishu: reply-in-thread, parallel group sessions, and fire-and-forget message handling #19784

@yinsn

Description

@yinsn

Summary

Three related improvements for the Feishu extension that significantly improve group chat UX:

  1. Always reply in thread — Add reply_in_thread: true to all im.message.reply calls in send.ts
  2. Parallel group timeline sessions — Use messageId as topic key for timeline messages (no rootId) so each message gets its own independent session
  3. Reply to thread root — Use ctx.rootId || ctx.messageId as replyToMessageId so replies go to the thread root instead of creating nested sub-threads
  4. Fire-and-forget message handling — Remove await on message dispatch in WebSocket mode (monitor.ts) so messages are processed in parallel without blocking the event loop

Motivation

Currently in group chats:

  • Bot replies appear on the main timeline, cluttering the chat
  • Messages are processed sequentially — if one takes 30s, the next one waits
  • Replying to a message inside a thread creates a nested sub-thread instead of keeping the conversation flat within the existing thread
  • Timeline messages in the same group share a single session, causing context mixing

These issues make the bot unusable in active group chats with multiple concurrent users.

Proposed Changes

1. reply_in_thread: true in send.ts

Add reply_in_thread: true to the data payload in all im.message.reply API calls. This keeps bot responses contained in threads.

2. Parallel group sessions in bot.ts

When topicSessionMode is enabled for a group, use ctx.rootId ?? ctx.messageId as the topic key instead of only ctx.rootId:

  • Thread replies (rootId present): share session by thread root (existing behavior)
  • Timeline messages (no rootId): each message gets its own session via messageId

This enables true parallel processing in group chats.

3. Reply to thread root in bot.ts

Change replyToMessageId: ctx.messageIdreplyToMessageId: ctx.rootId || ctx.messageId so that replies within a thread always target the root message, avoiding nested sub-threads.

4. Fire-and-forget in monitor.ts

In the WebSocket message handler, always use fire-and-forget (.catch() without await) regardless of the fireAndForget flag. Combined with per-message sessions (point 2), this is safe and dramatically improves throughput.

Related

Environment

  • Feishu extension: extensions/feishu/src/send.ts, bot.ts, monitor.ts
  • Tested with topicSessionMode: "enabled" in group config

Metadata

Metadata

Assignees

No one assigned

    Labels

    staleMarked as stale due to inactivity

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions