Skip to content

Commit 32cfcbf

Browse files
ScarletPupilclaudeSoulter
authored
feat: show quoted message content in group chat context
* feat: show quoted message content in group chat context Include Reply component content in _format_message so the LLM can see what message was quoted when someone replies to the bot. - Add Reply import - Handle Reply in _format_message with message_str or chain fallback - Add _describe_chain helper for non-text quoted content (images, etc.) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix: use isinstance, add truncation, unify language to English - Replace string class-name checks with isinstance() for robustness - Add _truncate_reply_text to prevent long quoted content inflating context - Unify markers to English ([Image], [Voice], [Quote] etc.) - Import Record, Video, File for isinstance checks Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix: add Forward, AtAll, Face to _describe_chain for completeness Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * style: format group chat context --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: Soulter <905617992@qq.com>
1 parent fb8f4d6 commit 32cfcbf

1 file changed

Lines changed: 62 additions & 1 deletion

File tree

astrbot/builtin_stars/astrbot/group_chat_context.py

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,18 @@
77
from astrbot import logger
88
from astrbot.api import star
99
from astrbot.api.event import AstrMessageEvent
10-
from astrbot.api.message_components import At, Image, Plain
10+
from astrbot.api.message_components import (
11+
At,
12+
AtAll,
13+
Face,
14+
File,
15+
Forward,
16+
Image,
17+
Plain,
18+
Record,
19+
Reply,
20+
Video,
21+
)
1122
from astrbot.api.platform import MessageType
1223
from astrbot.api.provider import Provider, ProviderRequest
1324
from astrbot.core.agent.message import TextPart
@@ -214,10 +225,60 @@ async def _format_message(self, event: AstrMessageEvent, cfg: dict) -> str:
214225
if is_at_self:
215226
parts.insert(1, "⚠️[DIRECTED AT YOU] ")
216227
parts.append(f" [At: {comp.name}]")
228+
elif isinstance(comp, Reply):
229+
if comp.message_str:
230+
parts.append(
231+
f" [Quote({comp.sender_nickname}: {_truncate_reply_text(comp.message_str)})]"
232+
)
233+
elif comp.chain:
234+
chain_desc = _describe_chain(comp.chain)
235+
parts.append(f" [Quote({comp.sender_nickname}: {chain_desc})]")
236+
else:
237+
parts.append(" [Quote]")
217238

218239
return "".join(parts)
219240

220241

242+
_MAX_REPLY_TEXT_LENGTH = 200
243+
244+
245+
def _describe_chain(chain: list) -> str:
246+
"""Summarize message chain content for quoted reply display."""
247+
desc = []
248+
for c in chain:
249+
if isinstance(c, Plain) and getattr(c, "text", None):
250+
desc.append(c.text)
251+
elif isinstance(c, Image):
252+
desc.append("[Image]")
253+
elif isinstance(c, At):
254+
name = getattr(c, "name", "") or getattr(c, "qq", "")
255+
desc.append(f"[At: {name}]")
256+
elif isinstance(c, Record):
257+
desc.append("[Voice]")
258+
elif isinstance(c, Video):
259+
desc.append("[Video]")
260+
elif isinstance(c, File):
261+
desc.append(f"[File: {getattr(c, 'name', '') or ''}]")
262+
elif isinstance(c, Forward):
263+
desc.append("[Forward]")
264+
elif isinstance(c, AtAll):
265+
desc.append("[At: All]")
266+
elif isinstance(c, Face):
267+
desc.append(f"[Sticker: {getattr(c, 'id', '')}]")
268+
elif isinstance(c, Reply):
269+
desc.append("[Quote]")
270+
else:
271+
desc.append(f"[{c.__class__.__name__}]")
272+
return "".join(desc) or "[Unknown]"
273+
274+
275+
def _truncate_reply_text(text: str) -> str:
276+
"""Truncate overly long quoted reply text."""
277+
if len(text) <= _MAX_REPLY_TEXT_LENGTH:
278+
return text
279+
return text[:_MAX_REPLY_TEXT_LENGTH] + "..."
280+
281+
221282
def _positive_int(value, fallback: int) -> int:
222283
try:
223284
parsed = int(value)

0 commit comments

Comments
 (0)