mirror of
https://gitee.com/wanwujie/deer-flow
synced 2026-04-24 14:44:46 +08:00
Merge upstream/experimental and resolve conflicts; citations + path_utils + mode-hover
## 冲突解决 (Resolve conflicts) - input-box.tsx: 保留 ModeHoverGuide 包裹的模式选择器(PR #26 的 mode-hover-guide) - message-group.tsx: 保留 getCleanContent / hasCitationsBlock / useParsedCitations - message-list-item.tsx: 保留 useParsedCitations,移除重复的 MessageLink(使用 CitationAwareLink) - artifact-file-detail.tsx: 保留 CitationAwareLink、useParsedCitations、contentWithoutCitationsFromParsed - artifacts.py: 保留 path_utils 与 _extract_citation_urls + remove_citations_block 精简实现 - citations/index.ts: 保留并补充 contentWithoutCitationsFromParsed 导出 - en-US.ts: 保留 Ultra 模式描述 "Reasoning, planning and execution with subagents..." - zh-CN.ts: 保留「超级」标签,描述保留「思考、计划并执行,可调用子代理分工协作...」 ## PR #26 代码改动汇总 ### 1. Citations(引用) - lead_agent prompt: 增加 Web search 与子代理合成时的 citation 提示 - general_purpose: 子代理 system prompt 增加 <citations_format> 说明 - frontend utils: 新增 contentWithoutCitationsFromParsed,removeAllCitations 基于单次解析 - frontend artifact: 使用 contentWithoutCitationsFromParsed(parsed) 避免对同一内容解析两次 - backend artifacts: _extract_citation_urls + remove_citations_block,json 提到顶部 ### 2. path_utils(路径解析) - 新增 backend/src/gateway/path_utils.py:resolve_thread_virtual_path,防 path traversal - artifacts.py / skills.py:删除内联路径解析,统一使用 path_utils ### 3. Mode hover guide - input-box: 模式选择器外包 ModeHoverGuide,悬停展示模式说明 ### 4. i18n - en: ultraModeDescription 与 zh: ultraMode / ultraModeDescription 与上游对齐并保留 PR 文案 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -34,7 +34,11 @@ import { CodeEditor } from "@/components/workspace/code-editor";
|
|||||||
import { useArtifactContent } from "@/core/artifacts/hooks";
|
import { useArtifactContent } from "@/core/artifacts/hooks";
|
||||||
import { urlOfArtifact } from "@/core/artifacts/utils";
|
import { urlOfArtifact } from "@/core/artifacts/utils";
|
||||||
import type { Citation } from "@/core/citations";
|
import type { Citation } from "@/core/citations";
|
||||||
import { removeAllCitations, useParsedCitations } from "@/core/citations";
|
import {
|
||||||
|
contentWithoutCitationsFromParsed,
|
||||||
|
removeAllCitations,
|
||||||
|
useParsedCitations,
|
||||||
|
} from "@/core/citations";
|
||||||
import { useI18n } from "@/core/i18n/hooks";
|
import { useI18n } from "@/core/i18n/hooks";
|
||||||
import { installSkill } from "@/core/skills/api";
|
import { installSkill } from "@/core/skills/api";
|
||||||
import { streamdownPlugins } from "@/core/streamdown";
|
import { streamdownPlugins } from "@/core/streamdown";
|
||||||
@@ -96,12 +100,10 @@ export function ArtifactFileDetail({
|
|||||||
);
|
);
|
||||||
const cleanContent =
|
const cleanContent =
|
||||||
language === "markdown" && content ? parsed.cleanContent : (content ?? "");
|
language === "markdown" && content ? parsed.cleanContent : (content ?? "");
|
||||||
const contentWithoutCitations = useMemo(() => {
|
const contentWithoutCitations =
|
||||||
if (language === "markdown" && content) {
|
language === "markdown" && content
|
||||||
return removeAllCitations(content);
|
? contentWithoutCitationsFromParsed(parsed)
|
||||||
}
|
: (content ?? "");
|
||||||
return content;
|
|
||||||
}, [content, language]);
|
|
||||||
|
|
||||||
const [viewMode, setViewMode] = useState<"code" | "preview">("code");
|
const [viewMode, setViewMode] = useState<"code" | "preview">("code");
|
||||||
const [isInstalling, setIsInstalling] = useState(false);
|
const [isInstalling, setIsInstalling] = useState(false);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
export {
|
export {
|
||||||
|
contentWithoutCitationsFromParsed,
|
||||||
extractDomainFromUrl,
|
extractDomainFromUrl,
|
||||||
getCleanContent,
|
getCleanContent,
|
||||||
hasCitationsBlock,
|
hasCitationsBlock,
|
||||||
|
|||||||
@@ -185,27 +185,25 @@ export function isCitationsBlockIncomplete(content: string): boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove ALL citations from content, including:
|
* Strip citation markdown links from already-cleaned content (from parseCitations).
|
||||||
* - <citations> blocks
|
* Use when you already have ParseCitationsResult to avoid parsing twice.
|
||||||
* - [cite-N] references (and their converted markdown links)
|
|
||||||
*
|
|
||||||
* Uses parseCitations once, then strips citation links from cleanContent.
|
|
||||||
* Used for copy/download to produce content without any citation references.
|
|
||||||
*
|
|
||||||
* @param content - The raw content that may contain citations
|
|
||||||
* @returns Content with all citations completely removed
|
|
||||||
*/
|
*/
|
||||||
export function removeAllCitations(content: string): string {
|
export function contentWithoutCitationsFromParsed(
|
||||||
if (!content) return content;
|
parsed: ParseCitationsResult,
|
||||||
|
): string {
|
||||||
const parsed = parseCitations(content);
|
|
||||||
const citationUrls = new Set(parsed.citations.map((c) => c.url));
|
const citationUrls = new Set(parsed.citations.map((c) => c.url));
|
||||||
|
|
||||||
// Remove markdown links that point to citation URLs; keep non-citation links
|
|
||||||
const withoutLinks = parsed.cleanContent.replace(
|
const withoutLinks = parsed.cleanContent.replace(
|
||||||
/\[([^\]]+)\]\(([^)]+)\)/g,
|
/\[([^\]]+)\]\(([^)]+)\)/g,
|
||||||
(fullMatch, _text, url) => (citationUrls.has(url) ? "" : fullMatch),
|
(fullMatch, _text, url) => (citationUrls.has(url) ? "" : fullMatch),
|
||||||
);
|
);
|
||||||
|
|
||||||
return withoutLinks.replace(/\n{3,}/g, "\n\n").trim();
|
return withoutLinks.replace(/\n{3,}/g, "\n\n").trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove ALL citations from content (blocks, [cite-N], and citation links).
|
||||||
|
* Used for copy/download. For display you typically use parseCitations/useParsedCitations.
|
||||||
|
*/
|
||||||
|
export function removeAllCitations(content: string): string {
|
||||||
|
if (!content) return content;
|
||||||
|
return contentWithoutCitationsFromParsed(parseCitations(content));
|
||||||
|
}
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ export const zhCN: Translations = {
|
|||||||
reasoningModeDescription: "思考后再行动,在时间与准确性之间取得平衡",
|
reasoningModeDescription: "思考后再行动,在时间与准确性之间取得平衡",
|
||||||
proMode: "Pro",
|
proMode: "Pro",
|
||||||
proModeDescription: "思考、计划再执行,获得更精准的结果,可能需要更多时间",
|
proModeDescription: "思考、计划再执行,获得更精准的结果,可能需要更多时间",
|
||||||
ultraMode: "Ultra",
|
ultraMode: "超级",
|
||||||
ultraModeDescription:
|
ultraModeDescription:
|
||||||
"思考、计划并执行,可调用子代理分工协作,适合复杂多步骤任务,能力最强",
|
"思考、计划并执行,可调用子代理分工协作,适合复杂多步骤任务,能力最强",
|
||||||
searchModels: "搜索模型...",
|
searchModels: "搜索模型...",
|
||||||
|
|||||||
Reference in New Issue
Block a user