From 662ee48533ae60bb4c4b43e583d8665cb5f1668a Mon Sep 17 00:00:00 2001 From: starmen1265 Date: Wed, 11 Mar 2026 13:02:18 +0800 Subject: [PATCH] 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 --- .../src/gsd_openclaw/response_formatter.py | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/gsd-openclaw/src/gsd_openclaw/response_formatter.py b/gsd-openclaw/src/gsd_openclaw/response_formatter.py index a7d7a9b..e4b75a1 100644 --- a/gsd-openclaw/src/gsd_openclaw/response_formatter.py +++ b/gsd-openclaw/src/gsd_openclaw/response_formatter.py @@ -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 + ] + }