hotfix(feishu): use emoji reaction as typing indicator#14799
Open
DeJeune wants to merge 6 commits intoCherryHQ:mainfrom
Open
hotfix(feishu): use emoji reaction as typing indicator#14799DeJeune wants to merge 6 commits intoCherryHQ:mainfrom
DeJeune wants to merge 6 commits intoCherryHQ:mainfrom
Conversation
Feishu has no native typing API. React to the user's latest message with THUMBSUP so users get visible feedback that the agent is processing, and remove the reaction once we reply (or on stream end / disconnect). Signed-off-by: suyao <sy20010504@gmail.com>
Collaborator
ousugo
approved these changes
May 4, 2026
Replace single THUMBSUP reaction with a 3-stage status indicator: - INHALE while processing (set on sendTypingIndicator) - OK_HAND when the reply is delivered (sendMessage / onStreamComplete) - CRY when the stream errors (onStreamError) Transitions only fire when an active typing reaction exists, so bare sendMessage calls (e.g. /new ack) don't get a stray DONE reaction. Signed-off-by: suyao <sy20010504@gmail.com>
Feishu's reaction API rejected INHALE and OK_HAND with HTTP 400 "reaction type is invalid". Switch to documented emoji_type values: THINKING (🤔) for processing and OK (👌) for done. CRY for error was already valid. Signed-off-by: suyao <sy20010504@gmail.com>
Switch to Feishu's native (camelCase) reactions for clearer semantics: Typing for processing, LGTM for done. CRY remains for error since Feishu has no native error sticker. Signed-off-by: suyao <sy20010504@gmail.com>
Changed the reaction type used in FeishuAdapter from 'LGTM' to 'OK' for consistency with Feishu's native emoji types. This aligns with the recent updates to use valid emoji types for reactions. Signed-off-by: suyao <sy20010504@gmail.com>
When the LLM errors before producing any text, no streaming card is created, so the previous onStreamError() only swapped the reaction to CRY and otherwise stayed silent — the user saw no error message in the chat. Extract sendRawMessage() (chunked send without reaction transitions) and call it from onStreamError() in the no-controller branch so the error is always delivered to the chat. Signed-off-by: suyao <sy20010504@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

What this PR does
Before this PR:
FeishuAdapter.sendTypingIndicatorwas a no-op because Feishu has no nativetyping API. Users sending a message to a Feishu agent had no visual signal
that the bot had received their message until the streaming card or first
reply appeared, which can take several seconds.
After this PR:
sendTypingIndicator(chatId)now adds aTHUMBSUPemoji reaction to theuser's most recent message in that chat (via
im.messageReaction.create),giving users immediate, in-thread feedback that the agent is processing.
The reaction is removed once we reply (
sendMessage), the streamingresponse finalizes (
onStreamComplete), the stream errors(
onStreamError), or the adapter disconnects. The same reaction is reusedidempotently across the 4 s typing-refresh interval, so no duplicate API
calls are made for one user message.
Fixes #
Why we need it and why it was done in this way
Feishu has no native typing/presence API for bots, so the only in-channel
signal we can produce before responding is a message reaction. Reacting to
the user's last message is the closest analog to "typing…" in Feishu's UX:
it appears in the same thread, costs one cheap API call, and is easy to
clean up.
The following tradeoffs were made:
THUMBSUPas the emoji. It's broadly supported across Feishu/Larktenants. The constant is documented and easy to swap.
message_idper chat in memory. This isacceptable because reactions are only meaningful for the most recent
user turn, and adapters are recreated on disconnect.
sendTypingIndicator(chatId)signature witha
messageId, to avoid touching every other channel adapter.The following alternatives were considered:
require deletion via a separate API and clutter the chat.
for several seconds.
Links to places where the discussion took place:
Breaking changes
None.
Special notes for your reviewer
sendMessage,onStreamComplete,onStreamError,performDisconnect) so thereaction does not linger after a reply.
debuglevel — typing feedback is best-effort and must never breakmessage handling.
mainper the v2 code-freeze policy because this is auser-visible UX gap fix scoped to one adapter, with no refactoring.
Checklist
Release note