feat(02-02): implement FeishuResponseFormatter class

- format_success() creates card with green theme
- format_error() creates card with red theme
- format_info() creates card with blue theme
- format_paginated() adds [N/M] marker
- _build_card() creates three-zone structure (header/elements/actions)
- _build_actions() creates interactive button elements

All 6 tests pass. Card JSON uses schema 2.0 with lark_md content.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-11 13:02:18 +08:00
parent 72a5ad4441
commit 662ee48533
@@ -23,3 +23,61 @@ class CardButton:
text: str
value: Dict[str, Any]
button_type: str = "primary" # primary, default, danger
class FeishuResponseFormatter:
"""Format responses as Feishu Card messages."""
def format_success(self, title: str, content: str,
buttons: Optional[List[CardButton]] = None) -> dict:
"""Format a success response card with green theme."""
return self._build_card(title, content, CardTheme.SUCCESS, buttons)
def format_error(self, title: str, content: str,
buttons: Optional[List[CardButton]] = None) -> dict:
"""Format an error response card with red theme."""
return self._build_card(title, content, CardTheme.ERROR, buttons)
def format_info(self, title: str, content: str,
buttons: Optional[List[CardButton]] = None) -> dict:
"""Format an info response card with blue theme."""
return self._build_card(title, content, CardTheme.INFO, buttons)
def format_paginated(self, title: str, content: str,
page: int, total_pages: int) -> dict:
"""Format a paginated response with [page/total] marker."""
footer = f"\n\n---\n[{page}/{total_pages}]"
return self._build_card(title, content + footer, CardTheme.INFO)
def _build_card(self, title: str, content: str, theme: CardTheme,
buttons: Optional[List[CardButton]] = None) -> dict:
"""Build complete card JSON structure."""
card = {
"schema": "2.0",
"config": {"wide_screen_mode": True},
"header": {
"title": {"tag": "plain_text", "content": title},
"template": theme.value
},
"elements": [
{"tag": "div", "text": {"tag": "lark_md", "content": content}}
]
}
if buttons:
card["elements"].append(self._build_actions(buttons))
return card
def _build_actions(self, buttons: List[CardButton]) -> dict:
"""Build actions element from button list."""
return {
"tag": "action",
"actions": [
{
"tag": "button",
"text": {"tag": "plain_text", "content": btn.text},
"type": btn.button_type,
"value": btn.value
}
for btn in buttons
]
}