From 81309bc9088604b50285aaafac385d692f510d20 Mon Sep 17 00:00:00 2001 From: Soulter <37870767+Soulter@users.noreply.github.com> Date: Fri, 9 Jan 2026 18:04:43 +0800 Subject: [PATCH] perf: enhance reply functionality to support selected text quoting (#4387) * feat(chat): enhance reply functionality to support selected text quoting * perf: improve ui * feat(chat): add label for tools used in tool calls and update translations * feat(chat): simplify reply handling by removing text truncation logic --- .../sources/webchat/webchat_adapter.py | 11 +- astrbot/dashboard/routes/chat.py | 6 +- dashboard/src/components/chat/Chat.vue | 20 +- dashboard/src/components/chat/ChatInput.vue | 73 +++++++- dashboard/src/components/chat/MessageList.vue | 173 +++++++++++++++++- dashboard/src/composables/useMessages.ts | 10 +- .../src/i18n/locales/en-US/features/chat.json | 3 +- .../src/i18n/locales/zh-CN/features/chat.json | 3 +- 8 files changed, 273 insertions(+), 26 deletions(-) diff --git a/astrbot/core/platform/sources/webchat/webchat_adapter.py b/astrbot/core/platform/sources/webchat/webchat_adapter.py index 43a562026..1ad68136e 100644 --- a/astrbot/core/platform/sources/webchat/webchat_adapter.py +++ b/astrbot/core/platform/sources/webchat/webchat_adapter.py @@ -124,17 +124,20 @@ class WebChatAdapter(Platform): part_type = part.get("type") if part_type == "plain": text = part.get("text", "") - components.append(Plain(text)) + components.append(Plain(text=text)) text_parts.append(text) elif part_type == "reply": message_id = part.get("message_id") reply_chain = [] - reply_message_str = "" + reply_message_str = part.get("selected_text", "") sender_id = None sender_name = None - # recursively get the content of the referenced message - if depth < max_depth and message_id: + if reply_message_str: + reply_chain = [Plain(text=reply_message_str)] + + # recursively get the content of the referenced message, if selected_text is empty + if not reply_message_str and depth < max_depth and message_id: history = await self._get_message_history(message_id) if history and history.content: reply_parts = history.content.get("message", []) diff --git a/astrbot/dashboard/routes/chat.py b/astrbot/dashboard/routes/chat.py index 71c3fecd3..6ee589316 100644 --- a/astrbot/dashboard/routes/chat.py +++ b/astrbot/dashboard/routes/chat.py @@ -166,7 +166,11 @@ class ChatRoute(Route): parts.append({"type": "plain", "text": part.get("text", "")}) elif part_type == "reply": parts.append( - {"type": "reply", "message_id": part.get("message_id")} + { + "type": "reply", + "message_id": part.get("message_id"), + "selected_text": part.get("selected_text", ""), + } ) elif attachment_id := part.get("attachment_id"): attachment = await self.db.get_attachment_by_id(attachment_id) diff --git a/dashboard/src/components/chat/Chat.vue b/dashboard/src/components/chat/Chat.vue index df90eb0e7..ad56a17fc 100644 --- a/dashboard/src/components/chat/Chat.vue +++ b/dashboard/src/components/chat/Chat.vue @@ -38,6 +38,7 @@ :isLoadingMessages="isLoadingMessages" @openImagePreview="openImagePreview" @replyMessage="handleReplyMessage" + @replyWithText="handleReplyWithText" ref="messageList" />
@@ -208,7 +209,7 @@ const prompt = ref(''); // 引用消息状态 interface ReplyInfo { messageId: number; // PlatformSessionHistoryMessage 的 id - messageContent: string; // 用于显示的消息内容 + selectedText?: string; // 选中的文本内容(可选) } const replyTo = ref(null); @@ -277,7 +278,7 @@ function handleReplyMessage(msg: any, index: number) { replyTo.value = { messageId, - messageContent: messageContent || '[媒体内容]' + selectedText: messageContent || '[媒体内容]' }; } @@ -285,6 +286,21 @@ function clearReply() { replyTo.value = null; } +function handleReplyWithText(replyData: any) { + // 处理选中文本的引用 + const { messageId, selectedText, messageIndex } = replyData; + + if (!messageId) { + console.warn('Message does not have an id'); + return; + } + + replyTo.value = { + messageId, + selectedText: selectedText // 保存原始的选中文本 + }; +} + async function handleSelectConversation(sessionIds: string[]) { if (!sessionIds[0]) return; diff --git a/dashboard/src/components/chat/ChatInput.vue b/dashboard/src/components/chat/ChatInput.vue index 4bc2c1a38..b403ef5e4 100644 --- a/dashboard/src/components/chat/ChatInput.vue +++ b/dashboard/src/components/chat/ChatInput.vue @@ -11,13 +11,15 @@ backgroundColor: isDark ? '#2d2d2d' : 'transparent' }"> -
-
- mdi-reply - "{{ props.replyTo.messageContent }}" + +
+
+ mdi-reply + "{{ props.replyTo.selectedText }}" +
+
- -
+