feat: include Feishu quoted message context

This commit is contained in:
AaronZ345
2026-07-17 17:09:48 +08:00
parent 7d8751f04b
commit 2635c12a7f
6 changed files with 209 additions and 1 deletions

View File

@@ -19,6 +19,7 @@ class FeishuMessage(ChatMessage):
self.msg_id = msg.get("message_id")
self.create_time = msg.get("create_time")
self.is_group = is_group
self.quoted_content = ""
msg_type = msg.get("message_type")
if msg_type == "text":
@@ -208,6 +209,9 @@ class FeishuMessage(ChatMessage):
else:
raise NotImplementedError("Unsupported message type: Type:{} ".format(msg_type))
if self.ctype == ContextType.TEXT:
self.quoted_content = self._fetch_quoted_content(msg.get("parent_id"))
self.from_user_id = sender.get("sender_id").get("open_id")
self.to_user_id = event.get("app_id")
if is_group:
@@ -220,3 +224,99 @@ class FeishuMessage(ChatMessage):
# 私聊
self.other_user_id = self.from_user_id
self.actual_user_id = self.from_user_id
def content_with_quote(self) -> str:
"""Return user text with optional quoted-message context for the agent."""
if not self.quoted_content:
return self.content
return (
"[Quoted message]\n{}\n[/Quoted message]\n\n{}".format(
self.quoted_content,
self.content,
)
)
def _fetch_quoted_content(self, parent_id: str) -> str:
"""Fetch one parent message, degrading to an empty quote on failure."""
if not parent_id or not self.access_token:
return ""
url = "https://open.feishu.cn/open-apis/im/v1/messages/{}".format(parent_id)
headers = {"Authorization": "Bearer " + self.access_token}
try:
response = requests.get(
url=url,
headers=headers,
params={"card_msg_content_type": "raw_card_content"},
timeout=(5, 10),
)
if response.status_code != 200:
logger.warning(
"[FeiShu] quoted message fetch failed, parent_id=%s, status=%s",
parent_id,
response.status_code,
)
return ""
body = response.json()
items = (body.get("data") or {}).get("items") or []
if body.get("code") != 0 or not items:
return ""
return self._extract_quoted_text(items[0])
except Exception as exc:
logger.warning(
"[FeiShu] quoted message fetch error, parent_id=%s: %s",
parent_id,
exc,
)
return ""
@staticmethod
def _extract_quoted_text(item: dict) -> str:
msg_type = item.get("msg_type")
raw_content = (item.get("body") or {}).get("content") or ""
try:
content = json.loads(raw_content)
except (TypeError, ValueError):
return ""
if msg_type == "text":
return str(content.get("text") or "").strip()
if msg_type == "post":
# Some message-history payloads wrap post content in a locale key.
if "content" not in content:
localized = next(
(value for value in content.values() if isinstance(value, dict)),
None,
)
if localized:
content = localized
parts = []
title = str(content.get("title") or "").strip()
if title:
parts.append(title)
for block in content.get("content") or []:
if not isinstance(block, list):
continue
for element in block:
if not isinstance(element, dict):
continue
tag = element.get("tag")
text = str(element.get("text") or "").strip()
if tag == "text" and text:
parts.append(text)
elif tag == "a" and text:
href = str(element.get("href") or "").strip()
parts.append("{} ({})".format(text, href) if href else text)
elif tag == "img":
parts.append("[Image]")
return "\n".join(parts).strip()
if msg_type == "image":
return "[Image]"
if msg_type == "file":
return "[File: {}]".format(content.get("file_name") or "file")
if msg_type == "audio":
return "[Audio]"
if msg_type == "media":
return "[Video: {}]".format(content.get("file_name") or "video")
return ""