feat: update skill settings

This commit is contained in:
Henry Li
2026-01-22 00:38:20 +08:00
parent 44850d9a61
commit b630e1846a
6 changed files with 75 additions and 25 deletions

4
frontend/TODO.md Normal file
View File

@@ -0,0 +1,4 @@
[ ] feat - Skills 页面根据 Category 分组展示
[ ] fix - autoOpen
[ ] fix - local settings
[ ] feat - todo

View File

@@ -153,7 +153,7 @@ export function InputBox({
: "text-muted-foreground", : "text-muted-foreground",
)} )}
> >
Thinking {t.inputBox.thinking}
</span> </span>
</> </>
</PromptInputButton> </PromptInputButton>

View File

@@ -1,8 +1,9 @@
"use client"; "use client";
import { SparklesIcon } from "lucide-react"; import { SparklesIcon } from "lucide-react";
import { useMemo, useState } from "react";
import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button";
import { import {
Empty, Empty,
EmptyDescription, EmptyDescription,
@@ -44,7 +45,13 @@ export function SkillSettingsPage() {
} }
function SkillSettingsList({ skills }: { skills: Skill[] }) { function SkillSettingsList({ skills }: { skills: Skill[] }) {
const { t } = useI18n();
const [filter, setFilter] = useState<"public" | "custom">("public");
const { mutate: enableSkill } = useEnableSkill(); const { mutate: enableSkill } = useEnableSkill();
const filteredSkills = useMemo(
() => skills.filter((skill) => skill.category === filter),
[skills, filter],
);
if (skills.length === 0) { if (skills.length === 0) {
return ( return (
<Empty> <Empty>
@@ -63,29 +70,59 @@ function SkillSettingsList({ skills }: { skills: Skill[] }) {
} }
return ( return (
<div className="flex w-full flex-col gap-4"> <div className="flex w-full flex-col gap-4">
{skills.map((skill) => ( <header className="flex gap-2">
<Item className="w-full" variant="outline" key={skill.name}> <Button
<ItemContent> className="rounded-xl"
<ItemTitle> size="sm"
<div className="flex items-center gap-2"> variant={filter === "public" ? "default" : "outline"}
<div>{skill.name}</div> onClick={() => setFilter("public")}
<Badge variant="outline">{skill.category}</Badge> >
</div> {t.common.public}
</ItemTitle> </Button>
<ItemDescription className="line-clamp-4"> <Button
{skill.description} className="rounded-xl"
</ItemDescription> size="sm"
</ItemContent> variant={filter === "custom" ? "default" : "outline"}
<ItemActions> onClick={() => setFilter("custom")}
<Switch >
checked={skill.enabled} {t.common.custom}
onCheckedChange={(checked) => </Button>
enableSkill({ skillName: skill.name, enabled: checked }) </header>
} {filteredSkills.length === 0 && (
/> <Empty>
</ItemActions> <EmptyHeader>
</Item> <EmptyMedia variant="icon">
))} <SparklesIcon />
</EmptyMedia>
<EmptyTitle>No skill yet</EmptyTitle>
<EmptyDescription>
Put your skill folders under the `/skills/{filter}` folder under
the root folder of DeerFlow.
</EmptyDescription>
</EmptyHeader>
</Empty>
)}
{filteredSkills.length > 0 &&
filteredSkills.map((skill) => (
<Item className="w-full" variant="outline" key={skill.name}>
<ItemContent>
<ItemTitle>
<div className="flex items-center gap-2">{skill.name}</div>
</ItemTitle>
<ItemDescription className="line-clamp-4">
{skill.description}
</ItemDescription>
</ItemContent>
<ItemActions>
<Switch
checked={skill.enabled}
onCheckedChange={(checked) =>
enableSkill({ skillName: skill.name, enabled: checked })
}
/>
</ItemActions>
</Item>
))}
</div> </div>
); );
} }

View File

@@ -18,6 +18,8 @@ export const enUS: Translations = {
download: "Download", download: "Download",
thinking: "Thinking", thinking: "Thinking",
artifacts: "Artifacts", artifacts: "Artifacts",
public: "Public",
custom: "Custom",
}, },
// Welcome // Welcome
@@ -37,6 +39,7 @@ export const enUS: Translations = {
// Input Box // Input Box
inputBox: { inputBox: {
placeholder: "How can I assist you today?", placeholder: "How can I assist you today?",
thinking: "Thinking",
thinkingEnabled: "Thinking is enabled", thinkingEnabled: "Thinking is enabled",
thinkingDisabled: "Thinking is disabled", thinkingDisabled: "Thinking is disabled",
clickToDisableThinking: "Click to disable thinking", clickToDisableThinking: "Click to disable thinking",

View File

@@ -16,6 +16,8 @@ export interface Translations {
download: string; download: string;
thinking: string; thinking: string;
artifacts: string; artifacts: string;
public: string;
custom: string;
}; };
// Welcome // Welcome
@@ -34,6 +36,7 @@ export interface Translations {
// Input Box // Input Box
inputBox: { inputBox: {
placeholder: string; placeholder: string;
thinking: string;
thinkingEnabled: string; thinkingEnabled: string;
thinkingDisabled: string; thinkingDisabled: string;
clickToDisableThinking: string; clickToDisableThinking: string;

View File

@@ -18,6 +18,8 @@ export const zhCN: Translations = {
download: "下载", download: "下载",
thinking: "思考", thinking: "思考",
artifacts: "文件", artifacts: "文件",
public: "公共",
custom: "自定义",
}, },
// Welcome // Welcome
@@ -37,6 +39,7 @@ export const zhCN: Translations = {
// Input Box // Input Box
inputBox: { inputBox: {
placeholder: "今天我能为你做些什么?", placeholder: "今天我能为你做些什么?",
thinking: "思考",
thinkingEnabled: "思考功能已启用", thinkingEnabled: "思考功能已启用",
thinkingDisabled: "思考功能已禁用", thinkingDisabled: "思考功能已禁用",
clickToDisableThinking: "点击禁用思考功能", clickToDisableThinking: "点击禁用思考功能",