fix(desktop): 修复搜索结果排版 — stripToolNarration 保留 markdown 结构
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
根因: stripToolNarration 按句子切分再用空格拼接,破坏了所有 markdown 格式(标题/列表/段落/代码块),导致搜索结果显示为纯文本墙。 修复: 改为按行处理,只过滤匹配叙述模式的行,保留 markdown 结构行 (标题/列表/空行/引用/代码/表格)。关键变化: - 保留空行(markdown 段落分隔符) - 保留以 #/-/*/数字/>/```/| 开头的结构行 - 仅过滤 LLM 内部叙述("让我执行..."、"Let me..."等)
This commit is contained in:
@@ -643,10 +643,14 @@ export function ChatArea({ compact, onOpenDetail }: { compact?: boolean; onOpenD
|
|||||||
* and Chinese ("让我执行...", "让我尝试..."). These are internal thoughts, not user-facing content.
|
* and Chinese ("让我执行...", "让我尝试..."). These are internal thoughts, not user-facing content.
|
||||||
*/
|
*/
|
||||||
function stripToolNarration(content: string): string {
|
function stripToolNarration(content: string): string {
|
||||||
const sentences = content.split(/(?<=[。!?.!?])\s*/);
|
// Process line-by-line to preserve markdown structure (headings, lists, paragraphs)
|
||||||
const filtered = sentences.filter(s => {
|
const lines = content.split('\n');
|
||||||
const t = s.trim();
|
const filtered = lines.filter(line => {
|
||||||
if (!t) return false;
|
const t = line.trim();
|
||||||
|
// Keep empty lines (paragraph breaks in markdown)
|
||||||
|
if (!t) return true;
|
||||||
|
// Keep markdown structural lines (headings, list items, horizontal rules, blockquotes, code)
|
||||||
|
if (/^(#{1,6}\s|[-*+]\s|\d+\.\s|>|\s*```|---|\|)/.test(t)) return true;
|
||||||
// English narration patterns
|
// English narration patterns
|
||||||
if (/^(?:Now )?[Ll]et me\s/i.test(t)) return false;
|
if (/^(?:Now )?[Ll]et me\s/i.test(t)) return false;
|
||||||
if (/^I\s+(?:need to|keep getting|should|will try|have to|can try|must)\s/i.test(t)) return false;
|
if (/^I\s+(?:need to|keep getting|should|will try|have to|can try|must)\s/i.test(t)) return false;
|
||||||
@@ -656,8 +660,8 @@ function stripToolNarration(content: string): string {
|
|||||||
if (/^好的,让我为您/.test(t)) return false;
|
if (/^好的,让我为您/.test(t)) return false;
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
const result = filtered.join(' ').replace(/\s{2,}/g, ' ').trim();
|
const result = filtered.join('\n');
|
||||||
return result || content; // Fallback: if everything was stripped, show original
|
return result || content;
|
||||||
}
|
}
|
||||||
|
|
||||||
function MessageBubble({ message, onRetry }: { message: Message; setInput?: (text: string) => void; onRetry?: () => void }) {
|
function MessageBubble({ message, onRetry }: { message: Message; setInput?: (text: string) => void; onRetry?: () => void }) {
|
||||||
|
|||||||
Reference in New Issue
Block a user