mirror of
https://gitee.com/wanwujie/deer-flow
synced 2026-04-25 23:14:46 +08:00
fix(citations): improve citation link rendering and copy behavior
- Use citation.title for display text in CitationLink to ensure correct titles show during streaming (instead of generic "Source" text) - Render all external links as CitationLink badges for consistent styling during streaming output - Add removeAllCitations when copying message content to clipboard - Simplify citations_format prompt for cleaner AI output Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -123,35 +123,25 @@ You have access to skills that provide optimized workflows for specific tasks. E
|
|||||||
</response_style>
|
</response_style>
|
||||||
|
|
||||||
<citations_format>
|
<citations_format>
|
||||||
**FORMAT** - After web_search, ALWAYS include citations in your output:
|
After web_search, ALWAYS include citations in your output and MUST start with a `<citations>` block in JSONL format:
|
||||||
**For chat responses:**
|
|
||||||
Your visible response MUST start with citations block, then content with inline links:
|
|
||||||
<citations>
|
<citations>
|
||||||
{{"id": "cite-1", "title": "Page Title", "url": "https://example.com/page", "snippet": "Brief description"}}
|
{{"id": "cite-1", "title": "Source Title 1", "url": "https://example.com/page1", "snippet": "Brief description of source 1"}}
|
||||||
|
...
|
||||||
</citations>
|
</citations>
|
||||||
Content with inline links...
|
|
||||||
|
|
||||||
**For files (write_file):**
|
**Rules:**
|
||||||
File content MUST start with citations block, then content with inline links:
|
- Write content naturally, add [Source Name](full_url) at end of sentence/paragraph
|
||||||
<citations>
|
|
||||||
{{"id": "cite-1", "title": "Page Title", "url": "https://example.com/page", "snippet": "Brief description"}}
|
|
||||||
</citations>
|
|
||||||
# Document Title
|
|
||||||
Content with inline [Source Name](full_url) links...
|
|
||||||
|
|
||||||
**RULES:**
|
|
||||||
- `<citations>` block MUST be FIRST (in both chat response AND file content)
|
|
||||||
- Write full content naturally, add [Source Name](full_url) at end of sentence/paragraph
|
|
||||||
- NEVER use "According to [Source]" format - write content first, then add citation link at end
|
- NEVER use "According to [Source]" format - write content first, then add citation link at end
|
||||||
- Example: "AI agents will transform digital work ([Microsoft](url))" NOT "According to [Microsoft](url), AI agents will..."
|
|
||||||
|
|
||||||
**Example:**
|
**Example:**
|
||||||
<citations>
|
<citations>
|
||||||
{{"id": "cite-1", "title": "AI Trends 2026", "url": "https://techcrunch.com/ai-trends", "snippet": "Tech industry predictions"}}
|
{{"id": "cite-1", "title": "AI Trends 2026", "url": "https://techcrunch.com/ai-trends", "snippet": "Tech industry predictions"}}
|
||||||
|
{{"id": "cite-2", "title": "OpenAI Research", "url": "https://openai.com/research", "snippet": "Latest AI research developments"}}
|
||||||
</citations>
|
</citations>
|
||||||
The key AI trends for 2026 include enhanced reasoning capabilities, multimodal integration, and improved efficiency [TechCrunch](https://techcrunch.com/ai-trends).
|
The key AI trends for 2026 include enhanced reasoning capabilities and multimodal integration [TechCrunch](https://techcrunch.com/ai-trends). Recent breakthroughs in language models have also accelerated progress [OpenAI](https://openai.com/research).
|
||||||
</citations_format>
|
</citations_format>
|
||||||
|
|
||||||
|
|
||||||
<critical_reminders>
|
<critical_reminders>
|
||||||
- **Clarification First**: ALWAYS clarify unclear/missing/ambiguous requirements BEFORE starting work - never assume or guess
|
- **Clarification First**: ALWAYS clarify unclear/missing/ambiguous requirements BEFORE starting work - never assume or guess
|
||||||
- Skill First: Always load the relevant skill before starting **complex** tasks.
|
- Skill First: Always load the relevant skill before starting **complex** tasks.
|
||||||
|
|||||||
@@ -309,6 +309,11 @@ export const CitationLink = ({
|
|||||||
children,
|
children,
|
||||||
}: CitationLinkProps) => {
|
}: CitationLinkProps) => {
|
||||||
const domain = extractDomainFromUrl(href);
|
const domain = extractDomainFromUrl(href);
|
||||||
|
|
||||||
|
// Priority: citation.title > domain
|
||||||
|
// When citation has title, use it for consistent display
|
||||||
|
// This ensures correct title shows even during streaming when children might be generic
|
||||||
|
const displayText = citation?.title || domain;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<InlineCitationCard>
|
<InlineCitationCard>
|
||||||
@@ -324,7 +329,7 @@ export const CitationLink = ({
|
|||||||
variant="secondary"
|
variant="secondary"
|
||||||
className="hover:bg-secondary/80 mx-0.5 cursor-pointer gap-1 rounded-full px-2 py-0.5 text-xs font-normal"
|
className="hover:bg-secondary/80 mx-0.5 cursor-pointer gap-1 rounded-full px-2 py-0.5 text-xs font-normal"
|
||||||
>
|
>
|
||||||
{children ?? domain}
|
{displayText}
|
||||||
<ExternalLinkIcon className="size-3" />
|
<ExternalLinkIcon className="size-3" />
|
||||||
</Badge>
|
</Badge>
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import {
|
|||||||
buildCitationMap,
|
buildCitationMap,
|
||||||
isCitationsBlockIncomplete,
|
isCitationsBlockIncomplete,
|
||||||
parseCitations,
|
parseCitations,
|
||||||
|
removeAllCitations,
|
||||||
} from "@/core/citations";
|
} from "@/core/citations";
|
||||||
import {
|
import {
|
||||||
extractContentFromMessage,
|
extractContentFromMessage,
|
||||||
@@ -62,11 +63,11 @@ export function MessageListItem({
|
|||||||
>
|
>
|
||||||
<div className="flex gap-1">
|
<div className="flex gap-1">
|
||||||
<CopyButton
|
<CopyButton
|
||||||
clipboardData={
|
clipboardData={removeAllCitations(
|
||||||
extractContentFromMessage(message) ??
|
extractContentFromMessage(message) ??
|
||||||
extractReasoningContentFromMessage(message) ??
|
extractReasoningContentFromMessage(message) ??
|
||||||
""
|
""
|
||||||
}
|
)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</MessageToolbar>
|
</MessageToolbar>
|
||||||
@@ -76,19 +77,25 @@ export function MessageListItem({
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Custom link component that handles citations and external links
|
* Custom link component that handles citations and external links
|
||||||
|
* All external links (http/https) are rendered as CitationLink badges
|
||||||
|
* to ensure consistent styling during streaming
|
||||||
*/
|
*/
|
||||||
function MessageLink({
|
function MessageLink({
|
||||||
href,
|
href,
|
||||||
children,
|
children,
|
||||||
citationMap,
|
citationMap,
|
||||||
...props
|
|
||||||
}: React.AnchorHTMLAttributes<HTMLAnchorElement> & {
|
}: React.AnchorHTMLAttributes<HTMLAnchorElement> & {
|
||||||
citationMap: Map<string, Citation>;
|
citationMap: Map<string, Citation>;
|
||||||
}) {
|
}) {
|
||||||
if (!href) return <span>{children}</span>;
|
if (!href) return <span>{children}</span>;
|
||||||
|
|
||||||
const citation = citationMap.get(href);
|
const citation = citationMap.get(href);
|
||||||
if (citation) {
|
|
||||||
|
// Check if it's an external link (http/https)
|
||||||
|
const isExternalLink = href.startsWith("http://") || href.startsWith("https://");
|
||||||
|
|
||||||
|
// All external links use CitationLink for consistent styling during streaming
|
||||||
|
if (isExternalLink) {
|
||||||
return (
|
return (
|
||||||
<CitationLink citation={citation} href={href}>
|
<CitationLink citation={citation} href={href}>
|
||||||
{children}
|
{children}
|
||||||
@@ -96,13 +103,11 @@ function MessageLink({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Internal/anchor links use simple anchor tag
|
||||||
return (
|
return (
|
||||||
<a
|
<a
|
||||||
href={href}
|
href={href}
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
className="text-primary underline underline-offset-2 hover:no-underline"
|
className="text-primary underline underline-offset-2 hover:no-underline"
|
||||||
{...props}
|
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
Reference in New Issue
Block a user