From a2e954b0f95a982d7c40405d5183352fe2ce9312 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A8=8B=E5=BA=8F=E5=91=98=E9=98=BF=E6=B1=9F=28Relakkes?= =?UTF-8?q?=29?= Date: Mon, 15 Jun 2026 17:32:53 +0800 Subject: [PATCH] fix(desktop): ignore log links in output cards (#714) Output target detection should not promote URLs or markdown links embedded in fenced log/code blocks into assistant output cards. Keep explicit localhost and file references outside code blocks routable. Tested: cd desktop && bun run test -- src/lib/assistantOutputTargets.test.ts src/components/chat/AssistantMessage.linkrouting.test.tsx Tested: cd desktop && bun run lint Confidence: high Scope-risk: narrow --- .../AssistantMessage.linkrouting.test.tsx | 18 ++++++++++++++ .../src/lib/assistantOutputTargets.test.ts | 24 +++++++++++++++++++ desktop/src/lib/assistantOutputTargets.ts | 8 +++++++ 3 files changed, 50 insertions(+) diff --git a/desktop/src/components/chat/AssistantMessage.linkrouting.test.tsx b/desktop/src/components/chat/AssistantMessage.linkrouting.test.tsx index 93d2c808..a192775f 100644 --- a/desktop/src/components/chat/AssistantMessage.linkrouting.test.tsx +++ b/desktop/src/components/chat/AssistantMessage.linkrouting.test.tsx @@ -80,6 +80,24 @@ describe('AssistantMessage output-target cards', () => { expect(screen.getByText('assistantOutputs.kind.localhost')).toBeInTheDocument() }) + it('does NOT render a localhost card for URLs shown inside a log code block', () => { + render( + , + ) + + expect(screen.queryByText('assistantOutputs.kind.localhost')).toBeNull() + }) + it('renders a card for a markdown link with its Markdown badge', () => { render( { ]) }) + it('ignores localhost URLs printed inside fenced log output', () => { + const targets = extractAssistantOutputTargets( + [ + '日志前 50 行:', + '```log', + '[08:29:36][INFO] 代理服务已启动: 127.0.0.1:15721', + '[08:29:36][INFO] Claude Live 配置已接管,代理地址: http://127.0.0.1:15721', + '```', + ].join('\n'), + { workDir }, + ) + + expect(targets).toEqual([]) + }) + + it('ignores markdown links printed inside fenced code blocks', () => { + const targets = extractAssistantOutputTargets( + ['```md', '调试输出: [preview](http://localhost:5173/) [page](index.html)', '```'].join('\n'), + { workDir }, + ) + + expect(targets).toEqual([]) + }) + it('keeps markdown localhost links as markdown-link targets with authored labels', () => { const targets = extractAssistantOutputTargets( '[Preview](http://localhost:4173) then http://localhost:4173', diff --git a/desktop/src/lib/assistantOutputTargets.ts b/desktop/src/lib/assistantOutputTargets.ts index 30fd4754..7ac3d578 100644 --- a/desktop/src/lib/assistantOutputTargets.ts +++ b/desktop/src/lib/assistantOutputTargets.ts @@ -105,6 +105,10 @@ export function extractAssistantOutputTargets( const localhostTarget = toLocalhostTarget(href) const fileTarget = toWorkspaceFileTarget(href, workDir) + if (isInCodeBlock(match.start, codeBlocks)) { + continue + } + if (!title) { continue } @@ -144,6 +148,10 @@ export function extractAssistantOutputTargets( continue } + if (isInCodeBlock(position, codeBlocks)) { + continue + } + const href = trimTrailingPunctuation(match[0] ?? '') if (!href) {