fix(feishu): enrich reply context for card and file replies#2144
fix(feishu): enrich reply context for card and file replies#2144alexhoshina merged 7 commits intosipeed:mainfrom
Conversation
yinwm
left a comment
There was a problem hiding this comment.
Thanks for the iteration! The reply context reconstruction is well-designed — best-effort with graceful degradation, proper timeout handling, and solid test coverage.
One blocking issue:
Debug marker in production log
feishu_64.go:106 — replyctx-v4 in the startup log is a debug artifact that should not ship to production:
// current
logger.InfoC("feishu", "Feishu channel started (websocket mode, replyctx-v4)")
// should be
logger.InfoC("feishu", "Feishu channel started (websocket mode)")Non-blocking suggestions for future PRs:
- The reply context functions (~200 lines) could be extracted to a separate
feishu_reply.go—feishu_64.gois already ~960 lines. - Consider a simple LRU cache for
fetchMessageByIDto avoid hitting Feishu API rate limits in high-traffic groups. - A doc comment on the
[replied_message]/[current_message]tag format would help future consumers parse the structured context.
Once the log line is cleaned up, this is ready to merge.
- Move reply-related functions to new feishu_reply.go - Move corresponding tests to feishu_reply_test.go - Extract magic number 600 to maxReplyContextLen constant - Unify replyTargetID/replyTargetFromMessage (prefer parent_id, fallback root_id) - Add source comment for containsFeishuUpgradePlaceholder
…ed media refs - resolveReplyTargetMessageID: only call fetchMessageByID fallback when ThreadId is set, avoiding unnecessary API calls for non-reply messages - prependReplyContext: prepend replied media refs before current media refs to maintain correct ordering
… downloads - Add messageCache (sync.Map) to FeishuChannel struct - Cache fetched messages with 30s TTL to avoid re-downloading attachments when multiple users reply to the same parent message in a thread - Cleanup expired entries on read access (no background goroutine needed)
|
906aded | fix(feishu): enrich reply context for card and file replies |
yinwm
left a comment
There was a problem hiding this comment.
Thanks for the iteration! The overall design is solid — the best-effort fallback strategy and tag sanitization are well thought out.
One blocking issue before we can merge:
Log version tag: feishu_64.go:106 — "replyctx-v4" in the startup log is a debug marker that will show in production. Please remove it and restore the original message:
logger.InfoC("feishu", "Feishu channel started (websocket mode)")Non-blocking suggestions (feel free to address in a follow-up):
- Consider an early-return in
handleMessageReceivewhen bothparent_idandroot_idare empty, to skip theprependReplyContextoverhead for non-reply messages. - The Unicode escapes in
containsFeishuUpgradePlaceholderwould be more readable as raw Chinese characters or a named constant. fetchMessageByIDassumesItems[0]is the target — a brief comment explaining this assumption would help future readers.
…MessageByID comment
|
The replyctx-v4 debug marker was already removed in commit 4b47541 (current code at line 104 shows just "Feishu channel started (websocket mode)" without the version tag). Please rebase to see the latest changes. This PR now includes all fixes: |
|
The replyctx-v4 debug marker was already removed in commit 4b47541. Current line 104 shows: Feishu channel started (websocket mode) without any version tag. All blocking and non-blocking items from previous review are now addressed: |
yinwm
left a comment
There was a problem hiding this comment.
Great improvements — file extraction, caching, early-return, and media ref prepend all look solid. CI green too.
One blocking bug:
Duplicate prependReplyContext call in handleMessageReceive
The function is invoked twice back-to-back — first unconditionally, then again inside the conditional guard. For reply messages this causes the reply context block to be nested (the second call sees content that already contains [replied_message] tags from the first call).
// First call (unconditional) — should be removed
content, mediaRefs = c.prependReplyContext(ctx, message, chatID, content, mediaRefs)
if content == "" {
content = "[empty message]"
}
// Second call (conditional) — keep this one
if replyTargetID(message) != "" || stringValue(message.ThreadId) != "" {
content, mediaRefs = c.prependReplyContext(ctx, message, chatID, content, mediaRefs)
}Fix: remove the first (unconditional) call block (~4 lines) and keep only the conditional one.
After this fix, ready to approve.
yinwm
left a comment
There was a problem hiding this comment.
Great improvements across the board — file extraction, caching, early-return guard, and the prepend fix for media refs all look solid. CI green too.
.
One blocking bug:
Duplicate prependReplyContext call in handleMessageReceive
The function is called twice in sequence — first unconditionally, then again inside a conditional guard. For reply messages, this causes nested context blocks duplication.
The fix: remove the first unconditional call block (lines ~466-470) and keep only the conditional one after it fix: if content == "" { content = "[empty message]" }
Non-blocking (minor): containsFeishuUpgradePlaceholder still uses Unicode escapes — consider using raw Chinese characters for readability.
.
EOF
|
删除 handleMessageReceive第一次无条件的 prependReplyContext 调用 |
yinwm
left a comment
There was a problem hiding this comment.
LGTM — all blocking issues from previous rounds have been addressed. The reply context reconstruction is solid with proper best-effort degradation, caching, and sanitization.
One minor nit for a follow-up (non-blocking): the Unicode escapes in containsFeishuUpgradePlaceholder could be raw Chinese characters for readability, as suggested in the previous review.
) * fix(feishu): enrich reply context for card and file replies * refactor(feishu): extract reply functions to feishu_reply.go - Move reply-related functions to new feishu_reply.go - Move corresponding tests to feishu_reply_test.go - Extract magic number 600 to maxReplyContextLen constant - Unify replyTargetID/replyTargetFromMessage (prefer parent_id, fallback root_id) - Add source comment for containsFeishuUpgradePlaceholder * fix(feishu): skip API fallback for non-thread messages, prepend replied media refs - resolveReplyTargetMessageID: only call fetchMessageByID fallback when ThreadId is set, avoiding unnecessary API calls for non-reply messages - prependReplyContext: prepend replied media refs before current media refs to maintain correct ordering * fix(feishu): add message cache for fetchMessageByID to avoid repeated downloads - Add messageCache (sync.Map) to FeishuChannel struct - Cache fetched messages with 30s TTL to avoid re-downloading attachments when multiple users reply to the same parent message in a thread - Cleanup expired entries on read access (no background goroutine needed) * fix(feishu): early-return for non-reply messages, add cache and fetchMessageByID comment * fix: remove duplicate test and fix gci import order * fix(feishu): remove duplicate prependReplyContext call
Summary
Validation
Closes #1915