feat(channels): add streaming typewriter card for Feishu#2501
feat(channels): add streaming typewriter card for Feishu#2501carlos999-hqsama wants to merge 2 commits intoagentscope-ai:mainfrom
Conversation
|
Hi @carlos999-hqsama, this is your 1st Pull Request. 📋 About PR TemplateTo help maintainers review your PR faster, please make sure to include:
Complete PR information helps speed up the review process. You can edit the PR description to add these details. 🙌 Join Developer CommunityThanks so much for your contribution! We'd love to invite you to join the official CoPaw developer group! You can find the Discord and DingTalk group links under the "Developer Community" section on our docs page: We truly appreciate your enthusiasm—and look forward to your future contributions! 😊 We'll review your PR soon. |
There was a problem hiding this comment.
Code Review
This pull request implements a streaming typewriter effect for the Feishu channel using the Cardkit v1 API, including documentation and unit tests. Key feedback includes fixing a potential TypeError during receiver info unpacking, removing redundant code and unused parameters, and replacing magic numbers with constants. It is also suggested to simplify boolean conditions for idiomatic Python and to add integration tests for the core streaming loop logic.
| if obj == "message" and status == RunStatus.Completed: | ||
| final_text = text or "" | ||
| # If we had an active card, finalize it | ||
| if card_id and card_id != "": |
Implement streaming card output using Feishu Cardkit v1 API: - Create streaming card on first token, update in background (60ms interval) - Feishu renders text character-by-character via streaming_config - Auto fallback to normal message on API failure - Controlled by FEISHU_STREAMING_ENABLED env var - Supports both feishu.cn and larksuite.com domains Co-authored-by: 贰柒 <27@copaw>
960fbb1 to
d4c7728
Compare
- Remove unused _stop_updater function - Remove unused final_text param from _card_close - Simplify 'card_id and card_id != ""' to 'card_id' (both occurrences) - Replace magic number 0.06 with _STREAMING_UPDATE_INTERVAL_SEC constant - Update _card_close test call signatures - Add integration tests for _run_process_loop_streaming lifecycle
Gemini Review 反馈已全部修复
31个测试全部通过,已push。 |
Gemini Review 各项修复对照1. 🔴 Critical — 2. 🟠 High — 3. 🟠 High — 4. 🟡 Medium — 5. 🟡 Medium — 6. 🟡 Medium — 31个测试全部通过。请帮忙逐条标记 Resolved,感谢。 |

Description
Add streaming typewriter card output to the Feishu channel. AI replies are displayed character by character in real time using the Feishu Cardkit v1 Streaming Card API, instead of being sent all at once after generation completes.
Related Issue: Relates to #1296, #1549
Security Considerations: Uses existing tenant token from
lark_oapi.core.token.TokenManager, no additional credentials required. Streaming is opt-in via environment variable.Type of Change
Component(s) Affected
Checklist
pre-commit run --all-fileslocally and it passespytest) and they passTesting
29 unit tests in
tests/unit/channels/test_feishu_streaming.pycovering:_is_streaming_enabled: env var parsing (true/false/unset)_next_stream_seq: monotonic sequence counter_feishu_base_url: feishu.cn vs larksuite.com_card_create: success, HTTP failure, feishu error code, schema validation_card_send: success, HTTP failure_card_update_text: success, HTTP failure, feishu error code, full-text push, URL validation_card_close: success, streaming_mode=false, HTTP failure no-raise, exception no-raise_extract_streaming_text: message/delta/content/nested/empty cases_run_process_looprouting: disabled → normal path, enabled → streaming pathLocal Verification Evidence
$ pre-commit run --files src/copaw/app/channels/feishu/channel.py tests/unit/channels/test_feishu_streaming.py check yaml...............................................................Passed check toml...............................................................Passed fix end of files.........................................................Passed mypy.....................................................................Passed black....................................................................Passed flake8...................................................................Passed pylint...................................................................Passed $ pytest tests/unit/channels/test_feishu_streaming.py -v 29 passed, 9 warnings in 3.37sHow to Enable
export FEISHU_STREAMING_ENABLED=trueRequires
im:card:writeandim:card:readpermissions in the Feishu app config. When disabled or on API failure, output automatically falls back to normal messages.Design Note
During streaming, the card may briefly display the model'''s thinking/reasoning process (e.g. tool-call planning). This is intentional — the thinking content is hidden once the final response is rendered and the card is finalized. This is by design, not a leak.