Skip to content

feat(lark): add Lark streaming card footer status#7766

Open
catDforD wants to merge 1 commit intoAstrBotDevs:masterfrom
catDforD:fix/feishu-footer-status-hints
Open

feat(lark): add Lark streaming card footer status#7766
catDforD wants to merge 1 commit intoAstrBotDevs:masterfrom
catDforD:fix/feishu-footer-status-hints

Conversation

@catDforD
Copy link
Copy Markdown
Contributor

@catDforD catDforD commented Apr 24, 2026

Closes #7743

Modifications / 改动点

  • 新增飞书流式卡片底部提示配置项:

    • platform_specific.lark.footer.status
    • platform_specific.lark.footer.elapsed
  • 为飞书 CardKit 流式回复卡片增加底部状态展示:

    • 开启 status 后,生成中显示 生成中...,完成后显示 已完成
    • 开启 elapsed 后,完成后显示 耗时 x.xs
    • 同时开启时,完成后显示 已完成 · 耗时 x.xs
  • 补充 WebUI 配置项文案的国际化翻译,覆盖 zh-CNen-USru-RU

  • 增加单元测试,覆盖 footer 文案生成和 CardKit footer 元素渲染逻辑

  • This is NOT a breaking change. / 这不是一个破坏性变更。

Screenshots or Test Results / 运行截图或测试结果

  • 配置界面新增:普通配置/平台配置/其它配置
image
  • 原始飞书流式输出示例
image
  • 流式卡片显示生成状态 & 生成耗时
image
  • 流式卡片显示生成耗时
image
  • 流式卡片显示生成状态(生成状态是动态的,此处只截了生成完成的状态,实际还会有"生成中"的状态)
image

Checklist / 检查清单

  • 😊 If there are new features added in the PR, I have discussed it with the authors through issues/emails, etc.
    / 如果 PR 中有新加入的功能,已经通过 Issue / 邮件等方式和作者讨论过。

  • 👀 My changes have been well-tested, and "Verification Steps" and "Screenshots" have been provided above.
    / 我的更改经过了良好的测试,并已在上方提供了“验证步骤”和“运行截图”

  • 🤓 I have ensured that no new dependencies are introduced, OR if new dependencies are introduced, they have been added to the appropriate locations in requirements.txt and pyproject.toml.
    / 我确保没有引入新依赖库,或者引入了新依赖库的同时将其添加到 requirements.txtpyproject.toml 文件相应位置。

  • 😮 My changes do not introduce malicious code.
    / 我的更改没有引入恶意代码。

Summary by Sourcery

Add configurable footer status information to Lark streaming cards, including generation state and elapsed time, and wire it through config, event handling, and rendering.

New Features:

  • Introduce Lark streaming card footer options to show generation status and elapsed time via platform-specific configuration flags.
  • Display dynamic footer text on Lark CardKit streaming replies reflecting in-progress and completed states with optional duration.
  • Expose new Lark footer configuration fields in the Web UI configuration metadata with localization support.

Enhancements:

  • Refactor Lark streaming card element IDs into constants to support additional elements like the footer.
  • Propagate platform-specific Lark footer configuration into the streaming response pipeline for use during card rendering.

Tests:

  • Add unit tests covering footer text generation logic and inclusion/omission of the footer element in created Lark streaming cards.

@dosubot dosubot Bot added size:L This PR changes 100-499 lines, ignoring generated files. area:platform The bug / feature is about IM platform adapter, such as QQ, Lark, Telegram, WebChat and so on. labels Apr 24, 2026
Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

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

Hey - I've left some high level feedback:

  • The footer status strings ("生成中...", "已完成", "耗时 {x.x}s") are currently hard-coded in Chinese inside _build_streaming_footer_text; consider sourcing these from the existing i18n infrastructure or configuration so they respect the user's language settings.
  • In _update_streaming_footer you early-return when not content, which means you can’t clear an existing footer; if you ever need to support hiding/resetting the footer dynamically, you may want to distinguish between None (no-op) and an empty string (explicitly clear).
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The footer status strings ("生成中...", "已完成", "耗时 {x.x}s") are currently hard-coded in Chinese inside `_build_streaming_footer_text`; consider sourcing these from the existing i18n infrastructure or configuration so they respect the user's language settings.
- In `_update_streaming_footer` you early-return when `not content`, which means you can’t clear an existing footer; if you ever need to support hiding/resetting the footer dynamically, you may want to distinguish between `None` (no-op) and an empty string (explicitly clear).

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a footer for Lark streaming cards, allowing users to see the generation status and elapsed time. Changes include new configuration options in the default config, updates to the Lark event handler to manage footer elements, and localization support in the dashboard. Review feedback suggests localizing hardcoded strings in the footer generation logic to support internationalization and refactoring duplicated code for updating card elements into a shared helper function to improve maintainability.

Comment on lines +794 to +796
parts.append("已完成" if completed else "生成中...")
if elapsed_enabled and completed and elapsed_seconds is not None:
parts.append(f"耗时 {elapsed_seconds:.1f}s")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The strings "已完成", "生成中...", and "耗时" are hardcoded in Chinese. To support the internationalization goals of the project (as seen in the config metadata translations for zh-CN, en-US, and ru-RU), these strings should be localized or made configurable via the platform settings.

Comment on lines +929 to +968
async def _update_streaming_footer(
self,
card_id: str,
content: str,
sequence: int,
) -> bool:
"""更新 CardKit 流式卡片底部状态文本。"""
if not content:
return True
if self.bot.cardkit is None:
logger.error("[Lark] API Client cardkit 模块未初始化")
return False

request = (
ContentCardElementRequest.builder()
.card_id(card_id)
.element_id(self.STREAMING_FOOTER_ELEMENT_ID)
.request_body(
ContentCardElementRequestBody.builder()
.content(content)
.sequence(sequence)
.uuid(str(uuid.uuid4()))
.build()
)
.build()
)

try:
response = await self.bot.cardkit.v1.card_element.acontent(request)
except Exception as e:
logger.debug(f"[Lark] 流式更新 footer 失败 (ignored): {e}")
return False

if not response.success():
logger.debug(
f"[Lark] 流式更新 footer 失败({response.code}): {response.msg}"
)
return False

return True
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

This method is almost identical to _update_streaming_text. Following the general rules of this repository, consider refactoring the common logic into a shared helper function (e.g., _update_streaming_element(card_id, element_id, content, sequence)) to improve maintainability and reduce code duplication.

References
  1. When implementing similar functionality for different cases (e.g., direct vs. quoted attachments), refactor the logic into a shared helper function to avoid code duplication.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:platform The bug / feature is about IM platform adapter, such as QQ, Lark, Telegram, WebChat and so on. size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

飞书通道建议

1 participant