""" 飞书消息卡片构建器 — 统一的交互卡片生成,含反馈按钮 所有飞书 App Service 和 WS Handler 共用此模块构建回复卡片。 """ from __future__ import annotations import json import logging from typing import Any, Dict, List, Optional logger = logging.getLogger(__name__) # 反馈按钮 action tag 标识 ACTION_FEEDBACK_THUMBS_UP = "feedback_thumbs_up" ACTION_FEEDBACK_THUMBS_DOWN = "feedback_thumbs_down" ACTION_FEEDBACK_REGENERATE = "feedback_regenerate" def build_reply_card( title: str, content: str, *, execution_log_id: Optional[str] = None, agent_name: Optional[str] = None, status: str = "info", detail_link: Optional[str] = None, include_feedback: bool = True, ) -> Dict[str, Any]: """构建 Agent 回复消息卡片。 Args: title: 卡片标题 content: 卡片正文(Markdown 格式) execution_log_id: 关联的执行日志 ID(用于反馈追踪) agent_name: Agent 名称 status: info / success / failed detail_link: 详情链接(可选) include_feedback: 是否包含反馈按钮 Returns: 飞书交互卡片 JSON """ color_map = {"success": "green", "failed": "red", "info": "blue"} color = color_map.get(status, "blue") elements: List[Dict[str, Any]] = [ {"tag": "markdown", "content": content}, ] # 反馈按钮行 if include_feedback and execution_log_id: feedback_value = { "execution_log_id": execution_log_id, "agent_name": agent_name or "", "card_title": title, } elements.append({ "tag": "action", "actions": [ { "tag": "button", "text": {"tag": "plain_text", "content": "👍 有用"}, "type": "primary", "value": json.dumps({**feedback_value, "action": ACTION_FEEDBACK_THUMBS_UP}), }, { "tag": "button", "text": {"tag": "plain_text", "content": "👎 无用"}, "type": "default", "value": json.dumps({**feedback_value, "action": ACTION_FEEDBACK_THUMBS_DOWN}), }, { "tag": "button", "text": {"tag": "plain_text", "content": "🔄 重试"}, "type": "default", "value": json.dumps({**feedback_value, "action": ACTION_FEEDBACK_REGENERATE}), }, ], }) # 详情链接 if detail_link: elements.append({ "tag": "action", "actions": [ { "tag": "button", "text": {"tag": "plain_text", "content": "查看详情"}, "url": detail_link, "type": "default", } ], }) return { "config": {"wide_screen_mode": True}, "header": { "title": {"tag": "plain_text", "content": title}, "template": color, }, "elements": elements, } def build_feedback_response_card( original_title: str, original_content: str, action: str, *, detail_link: Optional[str] = None, ) -> Dict[str, Any]: """构建反馈确认卡片(替换原有卡片)。 当用户点击反馈按钮后,替换原卡片为去反馈按钮的确认卡片。 """ if action == ACTION_FEEDBACK_THUMBS_UP: note = "✅ 已收到你的反馈:**有用**,感谢支持!" color = "green" elif action == ACTION_FEEDBACK_THUMBS_DOWN: note = "💡 已收到你的反馈:**无用**,我们会持续改进。" color = "red" else: note = "🔄 正在为你重新生成回复..." color = "blue" content = f"{note}\n\n---\n{original_content}" return build_reply_card( title=original_title, content=content, status="info", detail_link=detail_link, include_feedback=False, )