mirror of
https://gitee.com/wanwujie/deer-flow
synced 2026-04-18 20:14:44 +08:00
feat: support settings
This commit is contained in:
@@ -1,6 +1,11 @@
|
||||
import type { Translations } from "./types";
|
||||
|
||||
export const enUS: Translations = {
|
||||
// Locale meta
|
||||
locale: {
|
||||
localName: "English",
|
||||
},
|
||||
|
||||
// Common
|
||||
common: {
|
||||
home: "Home",
|
||||
@@ -83,4 +88,41 @@ export const enUS: Translations = {
|
||||
readFile: "Read file",
|
||||
writeFile: "Write file",
|
||||
},
|
||||
|
||||
// Settings
|
||||
settings: {
|
||||
title: "Settings",
|
||||
description: "Adjust how DeerFlow looks and behaves for you.",
|
||||
sections: {
|
||||
appearance: "Appearance",
|
||||
tools: "Tools",
|
||||
skills: "Skills",
|
||||
acknowledge: "Acknowledge",
|
||||
},
|
||||
appearance: {
|
||||
themeTitle: "Theme",
|
||||
themeDescription:
|
||||
"Choose how the interface follows your device or stays fixed.",
|
||||
system: "System",
|
||||
light: "Light",
|
||||
dark: "Dark",
|
||||
systemDescription: "Match the operating system preference automatically.",
|
||||
lightDescription: "Bright palette with higher contrast for daytime.",
|
||||
darkDescription: "Dim palette that reduces glare for focus.",
|
||||
languageTitle: "Language",
|
||||
languageDescription: "Switch between languages.",
|
||||
},
|
||||
tools: {
|
||||
title: "Tools",
|
||||
description: "Manage the configuration and enabled status of MCP tools.",
|
||||
},
|
||||
skills: {
|
||||
title: "Skills",
|
||||
description: "Manage the configuration and enabled status of the skills.",
|
||||
},
|
||||
acknowledge: {
|
||||
emptyTitle: "Acknowledgements",
|
||||
emptyDescription: "Credits and acknowledgements will show here.",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
export interface Translations {
|
||||
// Locale meta
|
||||
locale: {
|
||||
localName: string;
|
||||
};
|
||||
|
||||
// Common
|
||||
common: {
|
||||
home: string;
|
||||
@@ -80,4 +85,40 @@ export interface Translations {
|
||||
readFile: string;
|
||||
writeFile: string;
|
||||
};
|
||||
|
||||
// Settings
|
||||
settings: {
|
||||
title: string;
|
||||
description: string;
|
||||
sections: {
|
||||
appearance: string;
|
||||
tools: string;
|
||||
skills: string;
|
||||
acknowledge: string;
|
||||
};
|
||||
appearance: {
|
||||
themeTitle: string;
|
||||
themeDescription: string;
|
||||
system: string;
|
||||
light: string;
|
||||
dark: string;
|
||||
systemDescription: string;
|
||||
lightDescription: string;
|
||||
darkDescription: string;
|
||||
languageTitle: string;
|
||||
languageDescription: string;
|
||||
};
|
||||
tools: {
|
||||
title: string;
|
||||
description: string;
|
||||
};
|
||||
skills: {
|
||||
title: string;
|
||||
description: string;
|
||||
};
|
||||
acknowledge: {
|
||||
emptyTitle: string;
|
||||
emptyDescription: string;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
import type { Translations } from "./types";
|
||||
|
||||
export const zhCN: Translations = {
|
||||
// Locale meta
|
||||
locale: {
|
||||
localName: "中文",
|
||||
},
|
||||
|
||||
// Common
|
||||
common: {
|
||||
home: "首页",
|
||||
@@ -83,4 +88,40 @@ export const zhCN: Translations = {
|
||||
readFile: "读取文件",
|
||||
writeFile: "写入文件",
|
||||
},
|
||||
|
||||
// Settings
|
||||
settings: {
|
||||
title: "设置",
|
||||
description: "根据你的偏好调整 DeerFlow 的界面和行为。",
|
||||
sections: {
|
||||
appearance: "外观",
|
||||
tools: "工具",
|
||||
skills: "技能",
|
||||
acknowledge: "致谢",
|
||||
},
|
||||
appearance: {
|
||||
themeTitle: "主题",
|
||||
themeDescription: "跟随系统或选择固定的界面模式。",
|
||||
system: "系统",
|
||||
light: "浅色",
|
||||
dark: "深色",
|
||||
systemDescription: "自动匹配操作系统偏好。",
|
||||
lightDescription: "更明亮的配色,适合日间使用。",
|
||||
darkDescription: "更暗的配色,减少眩光方便专注。",
|
||||
languageTitle: "语言",
|
||||
languageDescription: "在不同语言之间切换。",
|
||||
},
|
||||
tools: {
|
||||
title: "工具",
|
||||
description: "管理 MCP 工具的配置和启用状态。",
|
||||
},
|
||||
skills: {
|
||||
title: "技能",
|
||||
description: "管理智能体的技能配置和启用状态。",
|
||||
},
|
||||
acknowledge: {
|
||||
emptyTitle: "致谢",
|
||||
emptyDescription: "相关的致谢信息会展示在这里。",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
24
frontend/src/core/mcp/api.ts
Normal file
24
frontend/src/core/mcp/api.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { env } from "@/env";
|
||||
|
||||
import type { MCPConfig } from "./types";
|
||||
|
||||
export async function loadMCPConfig() {
|
||||
const response = await fetch(
|
||||
`${env.NEXT_PUBLIC_BACKEND_BASE_URL}/api/mcp/config`,
|
||||
);
|
||||
return response.json() as Promise<MCPConfig>;
|
||||
}
|
||||
|
||||
export async function updateMCPConfig(config: MCPConfig) {
|
||||
const response = await fetch(
|
||||
`${env.NEXT_PUBLIC_BACKEND_BASE_URL}/api/mcp/config`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(config),
|
||||
},
|
||||
);
|
||||
return response.json();
|
||||
}
|
||||
44
frontend/src/core/mcp/hooks.ts
Normal file
44
frontend/src/core/mcp/hooks.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
|
||||
import { loadMCPConfig, updateMCPConfig } from "./api";
|
||||
|
||||
export function useMCPConfig() {
|
||||
const { data, isLoading, error } = useQuery({
|
||||
queryKey: ["mcpConfig"],
|
||||
queryFn: () => loadMCPConfig(),
|
||||
});
|
||||
return { config: data, isLoading, error };
|
||||
}
|
||||
|
||||
export function useEnableMCPServer() {
|
||||
const queryClient = useQueryClient();
|
||||
const { config } = useMCPConfig();
|
||||
return useMutation({
|
||||
mutationFn: async ({
|
||||
serverName,
|
||||
enabled,
|
||||
}: {
|
||||
serverName: string;
|
||||
enabled: boolean;
|
||||
}) => {
|
||||
if (!config) {
|
||||
throw new Error("MCP config not found");
|
||||
}
|
||||
if (!config.mcp_servers[serverName]) {
|
||||
throw new Error(`MCP server ${serverName} not found`);
|
||||
}
|
||||
await updateMCPConfig({
|
||||
mcp_servers: {
|
||||
...config.mcp_servers,
|
||||
[serverName]: {
|
||||
...config.mcp_servers[serverName],
|
||||
enabled,
|
||||
},
|
||||
},
|
||||
});
|
||||
},
|
||||
onSuccess: () => {
|
||||
void queryClient.invalidateQueries({ queryKey: ["mcpConfig"] });
|
||||
},
|
||||
});
|
||||
}
|
||||
2
frontend/src/core/mcp/index.ts
Normal file
2
frontend/src/core/mcp/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from "./api";
|
||||
export * from "./types";
|
||||
8
frontend/src/core/mcp/types.ts
Normal file
8
frontend/src/core/mcp/types.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
export interface MCPServerConfig extends Record<string, unknown> {
|
||||
enabled: boolean;
|
||||
description: string;
|
||||
}
|
||||
|
||||
export interface MCPConfig {
|
||||
mcp_servers: Record<string, MCPServerConfig>;
|
||||
}
|
||||
25
frontend/src/core/skills/api.ts
Normal file
25
frontend/src/core/skills/api.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { env } from "@/env";
|
||||
|
||||
import type { Skill } from "./type";
|
||||
|
||||
export async function loadSkills() {
|
||||
const skills = await fetch(`${env.NEXT_PUBLIC_BACKEND_BASE_URL}/api/skills`);
|
||||
const json = await skills.json();
|
||||
return json.skills as Skill[];
|
||||
}
|
||||
|
||||
export async function enableSkill(skillName: string, enabled: boolean) {
|
||||
const response = await fetch(
|
||||
`${env.NEXT_PUBLIC_BACKEND_BASE_URL}/api/skills/${skillName}`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
enabled,
|
||||
}),
|
||||
},
|
||||
);
|
||||
return response.json();
|
||||
}
|
||||
31
frontend/src/core/skills/hooks.ts
Normal file
31
frontend/src/core/skills/hooks.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
|
||||
import { enableSkill } from "./api";
|
||||
|
||||
import { loadSkills } from ".";
|
||||
|
||||
export function useSkills() {
|
||||
const { data, isLoading, error } = useQuery({
|
||||
queryKey: ["skills"],
|
||||
queryFn: () => loadSkills(),
|
||||
});
|
||||
return { skills: data ?? [], isLoading, error };
|
||||
}
|
||||
|
||||
export function useEnableSkill() {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: async ({
|
||||
skillName,
|
||||
enabled,
|
||||
}: {
|
||||
skillName: string;
|
||||
enabled: boolean;
|
||||
}) => {
|
||||
await enableSkill(skillName, enabled);
|
||||
},
|
||||
onSuccess: () => {
|
||||
void queryClient.invalidateQueries({ queryKey: ["skills"] });
|
||||
},
|
||||
});
|
||||
}
|
||||
2
frontend/src/core/skills/index.ts
Normal file
2
frontend/src/core/skills/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from "./api";
|
||||
export * from "./type";
|
||||
7
frontend/src/core/skills/type.ts
Normal file
7
frontend/src/core/skills/type.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
export interface Skill {
|
||||
name: string;
|
||||
description: string;
|
||||
category: string;
|
||||
license: string;
|
||||
enabled: boolean;
|
||||
}
|
||||
Reference in New Issue
Block a user