Files
aiagent/backend/app/services/feishu_card_builder.py

136 lines
4.1 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
飞书消息卡片构建器 — 统一的交互卡片生成,含反馈按钮
所有飞书 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,
)