Merge pull request #31 from LofiSu/experimental

Experimental
This commit is contained in:
LofiSu
2026-02-10 12:31:55 +08:00
committed by GitHub
8 changed files with 81 additions and 48 deletions

View File

@@ -73,6 +73,7 @@
"react-dom": "^19.0.0", "react-dom": "^19.0.0",
"react-resizable-panels": "^4.4.1", "react-resizable-panels": "^4.4.1",
"rehype-katex": "^7.0.1", "rehype-katex": "^7.0.1",
"rehype-raw": "^7.0.0",
"remark-gfm": "^4.0.1", "remark-gfm": "^4.0.1",
"remark-math": "^6.0.0", "remark-math": "^6.0.0",
"shiki": "3.15.0", "shiki": "3.15.0",

View File

@@ -182,6 +182,9 @@ importers:
rehype-katex: rehype-katex:
specifier: ^7.0.1 specifier: ^7.0.1
version: 7.0.1 version: 7.0.1
rehype-raw:
specifier: ^7.0.0
version: 7.0.0
remark-gfm: remark-gfm:
specifier: ^4.0.1 specifier: ^4.0.1
version: 4.0.1 version: 4.0.1

View File

@@ -31,6 +31,26 @@ function confidenceToLevelKey(confidence: unknown): {
return { key: "normal", value }; return { key: "normal", value };
} }
function formatMemorySection(
title: string,
summary: string,
updatedAt: string | undefined,
t: ReturnType<typeof useI18n>["t"],
): string {
const content =
summary.trim() ||
`<span class="text-muted-foreground">${t.settings.memory.markdown.empty}</span>`;
return [
`### ${title}`,
content,
"",
updatedAt &&
`> ${t.settings.memory.markdown.updatedAt}: \`${formatTimeAgo(updatedAt)}\``,
]
.filter(Boolean)
.join("\n");
}
function memoryToMarkdown( function memoryToMarkdown(
memory: UserMemory, memory: UserMemory,
t: ReturnType<typeof useI18n>["t"], t: ReturnType<typeof useI18n>["t"],
@@ -44,65 +64,61 @@ function memoryToMarkdown(
parts.push(`\n## ${t.settings.memory.markdown.userContext}`); parts.push(`\n## ${t.settings.memory.markdown.userContext}`);
parts.push( parts.push(
[ formatMemorySection(
`### ${t.settings.memory.markdown.work}`, t.settings.memory.markdown.work,
memory.user.workContext.summary || "-", memory.user.workContext.summary,
"", memory.user.workContext.updatedAt,
memory.user.workContext.updatedAt && t,
`> ${t.settings.memory.markdown.updatedAt}: \`${formatTimeAgo(memory.user.workContext.updatedAt)}\``, ),
].join("\n"),
); );
parts.push( parts.push(
[ formatMemorySection(
`### ${t.settings.memory.markdown.personal}`, t.settings.memory.markdown.personal,
memory.user.personalContext.summary || "-", memory.user.personalContext.summary,
"", memory.user.personalContext.updatedAt,
memory.user.personalContext.updatedAt && t,
`> ${t.settings.memory.markdown.updatedAt}: \`${formatTimeAgo(memory.user.personalContext.updatedAt)}\``, ),
].join("\n"),
); );
parts.push( parts.push(
[ formatMemorySection(
`### ${t.settings.memory.markdown.topOfMind}`, t.settings.memory.markdown.topOfMind,
memory.user.topOfMind.summary || "-", memory.user.topOfMind.summary,
"", memory.user.topOfMind.updatedAt,
memory.user.topOfMind.updatedAt && t,
`> ${t.settings.memory.markdown.updatedAt}: \`${formatTimeAgo(memory.user.topOfMind.updatedAt)}\``, ),
].join("\n"),
); );
parts.push(`\n## ${t.settings.memory.markdown.historyBackground}`); parts.push(`\n## ${t.settings.memory.markdown.historyBackground}`);
parts.push( parts.push(
[ formatMemorySection(
`### ${t.settings.memory.markdown.recentMonths}`, t.settings.memory.markdown.recentMonths,
memory.history.recentMonths.summary || "-", memory.history.recentMonths.summary,
"", memory.history.recentMonths.updatedAt,
memory.history.recentMonths.updatedAt && t,
`> ${t.settings.memory.markdown.updatedAt}: \`${formatTimeAgo(memory.history.recentMonths.updatedAt)}\``, ),
].join("\n"),
); );
parts.push( parts.push(
[ formatMemorySection(
`### ${t.settings.memory.markdown.earlierContext}`, t.settings.memory.markdown.earlierContext,
memory.history.earlierContext.summary || "-", memory.history.earlierContext.summary,
"", memory.history.earlierContext.updatedAt,
memory.history.earlierContext.updatedAt && t,
`> ${t.settings.memory.markdown.updatedAt}: \`${formatTimeAgo(memory.history.earlierContext.updatedAt)}\``, ),
].join("\n"),
); );
parts.push( parts.push(
[ formatMemorySection(
`### ${t.settings.memory.markdown.longTermBackground}`, t.settings.memory.markdown.longTermBackground,
memory.history.longTermBackground.summary || "-", memory.history.longTermBackground.summary,
"", memory.history.longTermBackground.updatedAt,
memory.history.longTermBackground.updatedAt && t,
`> ${t.settings.memory.markdown.updatedAt}: \`${formatTimeAgo(memory.history.longTermBackground.updatedAt)}\``, ),
].join("\n"),
); );
parts.push(`\n## ${t.settings.memory.markdown.facts}`); parts.push(`\n## ${t.settings.memory.markdown.facts}`);
if (memory.facts.length === 0) { if (memory.facts.length === 0) {
parts.push(`_${t.settings.memory.markdown.empty}_`); parts.push(
`<span class="text-muted-foreground">${t.settings.memory.markdown.empty}</span>`,
);
} else { } else {
parts.push( parts.push(
[ [

View File

@@ -115,20 +115,20 @@ function SkillSettingsList({
} }
function EmptySkill({ onCreateSkill }: { onCreateSkill: () => void }) { function EmptySkill({ onCreateSkill }: { onCreateSkill: () => void }) {
const { t } = useI18n();
return ( return (
<Empty> <Empty>
<EmptyHeader> <EmptyHeader>
<EmptyMedia variant="icon"> <EmptyMedia variant="icon">
<SparklesIcon /> <SparklesIcon />
</EmptyMedia> </EmptyMedia>
<EmptyTitle>No agent skill yet</EmptyTitle> <EmptyTitle>{t.settings.skills.emptyTitle}</EmptyTitle>
<EmptyDescription> <EmptyDescription>
Put your agent skill folders under the `/skills/custom` folder under {t.settings.skills.emptyDescription}
the root folder of DeerFlow.
</EmptyDescription> </EmptyDescription>
</EmptyHeader> </EmptyHeader>
<EmptyContent> <EmptyContent>
<Button onClick={onCreateSkill}>Create Your First Skill</Button> <Button onClick={onCreateSkill}>{t.settings.skills.emptyButton}</Button>
</EmptyContent> </EmptyContent>
</Empty> </Empty>
); );

View File

@@ -243,7 +243,7 @@ export const enUS: Translations = {
longTermBackground: "Long-term background", longTermBackground: "Long-term background",
updatedAt: "Updated at", updatedAt: "Updated at",
facts: "Facts", facts: "Facts",
empty: "Empty", empty: "(empty)",
table: { table: {
category: "Category", category: "Category",
confidence: "Confidence", confidence: "Confidence",
@@ -282,6 +282,10 @@ export const enUS: Translations = {
description: description:
"Manage the configuration and enabled status of the agent skills.", "Manage the configuration and enabled status of the agent skills.",
createSkill: "Create skill", createSkill: "Create skill",
emptyTitle: "No agent skill yet",
emptyDescription:
"Put your agent skill folders under the `/skills/custom` folder under the root folder of DeerFlow.",
emptyButton: "Create Your First Skill",
}, },
notification: { notification: {
title: "Notification", title: "Notification",

View File

@@ -225,6 +225,9 @@ export interface Translations {
title: string; title: string;
description: string; description: string;
createSkill: string; createSkill: string;
emptyTitle: string;
emptyDescription: string;
emptyButton: string;
}; };
notification: { notification: {
title: string; title: string;

View File

@@ -275,6 +275,10 @@ export const zhCN: Translations = {
title: "技能", title: "技能",
description: "管理 Agent Skill 配置和启用状态。", description: "管理 Agent Skill 配置和启用状态。",
createSkill: "新建技能", createSkill: "新建技能",
emptyTitle: "还没有技能",
emptyDescription:
"将你的 Agent Skill 文件夹放在 DeerFlow 根目录下的 `/skills/custom` 文件夹中。",
emptyButton: "创建你的第一个技能",
}, },
notification: { notification: {
title: "通知", title: "通知",

View File

@@ -1,4 +1,5 @@
import rehypeKatex from "rehype-katex"; import rehypeKatex from "rehype-katex";
import rehypeRaw from "rehype-raw";
import remarkGfm from "remark-gfm"; import remarkGfm from "remark-gfm";
import remarkMath from "remark-math"; import remarkMath from "remark-math";
import type { StreamdownProps } from "streamdown"; import type { StreamdownProps } from "streamdown";
@@ -11,6 +12,7 @@ export const streamdownPlugins = {
[remarkMath, { singleDollarTextMath: true }], [remarkMath, { singleDollarTextMath: true }],
] as StreamdownProps["remarkPlugins"], ] as StreamdownProps["remarkPlugins"],
rehypePlugins: [ rehypePlugins: [
rehypeRaw,
[rehypeKatex, { output: "html" }], [rehypeKatex, { output: "html" }],
] as StreamdownProps["rehypePlugins"], ] as StreamdownProps["rehypePlugins"],
}; };