mirror of
https://gitee.com/wanwujie/deer-flow
synced 2026-04-19 04:14:46 +08:00
feat: add 'about' page
This commit is contained in:
@@ -9,6 +9,12 @@ const config = {
|
|||||||
devIndicators: false,
|
devIndicators: false,
|
||||||
turbopack: {
|
turbopack: {
|
||||||
root: import.meta.dirname,
|
root: import.meta.dirname,
|
||||||
|
rules: {
|
||||||
|
"*.md": {
|
||||||
|
loaders: ["raw-loader"],
|
||||||
|
as: "*.js",
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -97,6 +97,7 @@
|
|||||||
"postcss": "^8.5.3",
|
"postcss": "^8.5.3",
|
||||||
"prettier": "^3.5.3",
|
"prettier": "^3.5.3",
|
||||||
"prettier-plugin-tailwindcss": "^0.6.11",
|
"prettier-plugin-tailwindcss": "^0.6.11",
|
||||||
|
"raw-loader": "^4.0.2",
|
||||||
"tailwindcss": "^4.0.15",
|
"tailwindcss": "^4.0.15",
|
||||||
"tw-animate-css": "^1.4.0",
|
"tw-animate-css": "^1.4.0",
|
||||||
"typescript": "^5.8.2",
|
"typescript": "^5.8.2",
|
||||||
|
|||||||
571
frontend/pnpm-lock.yaml
generated
571
frontend/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,9 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { Streamdown } from "streamdown";
|
||||||
|
|
||||||
|
import about from "./about.md";
|
||||||
|
|
||||||
|
export function AboutSettingsPage() {
|
||||||
|
return <Streamdown>{about}</Streamdown>;
|
||||||
|
}
|
||||||
52
frontend/src/components/workspace/settings/about.md
Normal file
52
frontend/src/components/workspace/settings/about.md
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
# 🦌 [About DeerFlow 2.0](https://github.com/bytedance/deer-flow)
|
||||||
|
|
||||||
|
> **From Open Source, Back to Open Source**
|
||||||
|
|
||||||
|
**DeerFlow** (**D**eep **E**xploration and **E**fficient **R**esearch **Flow**) is a community-driven SuperAgent harness that researches, codes, and creates.
|
||||||
|
With the help of sandboxes, memories, tools and skills, it handles
|
||||||
|
different levels of tasks that could take minutes to hours.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🌟 GitHub Repository
|
||||||
|
|
||||||
|
Explore DeerFlow on GitHub: [github.com/bytedance/deer-flow](https://github.com/bytedance/deer-flow)
|
||||||
|
|
||||||
|
## 🌐 Official Website
|
||||||
|
|
||||||
|
Visit the official website of DeerFlow: [deerflow.tech](https://deerflow.tech/)
|
||||||
|
|
||||||
|
## 📧 Support
|
||||||
|
|
||||||
|
If you have any questions or need help, please contact us at [support@deerflow.tech](mailto:support@deerflow.tech).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📜 License
|
||||||
|
|
||||||
|
DeerFlow is proudly open source and distributed under the **MIT License**.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🙌 Acknowledgments
|
||||||
|
|
||||||
|
We extend our heartfelt gratitude to the open source projects and contributors who have made DeerFlow a reality. We truly stand on the shoulders of giants.
|
||||||
|
|
||||||
|
### Core Frameworks
|
||||||
|
- **[LangChain](https://github.com/langchain-ai/langchain)**: A phenomenal framework that powers our LLM interactions and chains.
|
||||||
|
- **[LangGraph](https://github.com/langchain-ai/langgraph)**: Enabling sophisticated multi-agent orchestration.
|
||||||
|
- **[Next.js](https://nextjs.org/)**: A cutting-edge framework for building web applications.
|
||||||
|
|
||||||
|
### UI Libraries
|
||||||
|
- **[Shadcn](https://ui.shadcn.com/)**: Minimalistic components that power our UI.
|
||||||
|
- **[SToneX](https://github.com/stonexer)**: For his invaluable contribution to token-by-token visual effects.
|
||||||
|
|
||||||
|
These outstanding projects form the backbone of DeerFlow and exemplify the transformative power of open source collaboration.
|
||||||
|
|
||||||
|
### Special Thanks
|
||||||
|
Finally, we want to express our heartfelt gratitude to the core authors of DeerFlow 1.0 and 2.0:
|
||||||
|
|
||||||
|
- **[Daniel Walnut](https://github.com/hetaoBackend/)**
|
||||||
|
- **[Henry Li](https://github.com/magiccube/)**
|
||||||
|
|
||||||
|
Without their vision, passion and dedication, `DeerFlow` would not be what it is today.
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
"use client";
|
|
||||||
|
|
||||||
export function AcknowledgePage() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
@@ -40,7 +40,6 @@ function memoryToMarkdown(
|
|||||||
console.info(memory);
|
console.info(memory);
|
||||||
|
|
||||||
parts.push(`## ${t.settings.memory.markdown.overview}`);
|
parts.push(`## ${t.settings.memory.markdown.overview}`);
|
||||||
parts.push(`- **${t.common.version}**: \`${memory.version}\``);
|
|
||||||
parts.push(
|
parts.push(
|
||||||
`- **${t.common.lastUpdated}**: \`${formatTimeAgo(memory.lastUpdated)}\``,
|
`- **${t.common.lastUpdated}**: \`${formatTimeAgo(memory.lastUpdated)}\``,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -2,12 +2,13 @@
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
BellIcon,
|
BellIcon,
|
||||||
|
InfoIcon,
|
||||||
BrainIcon,
|
BrainIcon,
|
||||||
PaletteIcon,
|
PaletteIcon,
|
||||||
SparklesIcon,
|
SparklesIcon,
|
||||||
WrenchIcon,
|
WrenchIcon,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { useMemo, useState } from "react";
|
import { useEffect, useMemo, useState } from "react";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Dialog,
|
Dialog,
|
||||||
@@ -16,7 +17,7 @@ import {
|
|||||||
DialogTitle,
|
DialogTitle,
|
||||||
} from "@/components/ui/dialog";
|
} from "@/components/ui/dialog";
|
||||||
import { ScrollArea } from "@/components/ui/scroll-area";
|
import { ScrollArea } from "@/components/ui/scroll-area";
|
||||||
import { AcknowledgePage } from "@/components/workspace/settings/acknowledge-page";
|
import { AboutSettingsPage } from "@/components/workspace/settings/about-settings-page";
|
||||||
import { AppearanceSettingsPage } from "@/components/workspace/settings/appearance-settings-page";
|
import { AppearanceSettingsPage } from "@/components/workspace/settings/appearance-settings-page";
|
||||||
import { MemorySettingsPage } from "@/components/workspace/settings/memory-settings-page";
|
import { MemorySettingsPage } from "@/components/workspace/settings/memory-settings-page";
|
||||||
import { NotificationSettingsPage } from "@/components/workspace/settings/notification-settings-page";
|
import { NotificationSettingsPage } from "@/components/workspace/settings/notification-settings-page";
|
||||||
@@ -31,7 +32,7 @@ type SettingsSection =
|
|||||||
| "tools"
|
| "tools"
|
||||||
| "skills"
|
| "skills"
|
||||||
| "notification"
|
| "notification"
|
||||||
| "acknowledge";
|
| "about";
|
||||||
|
|
||||||
type SettingsDialogProps = React.ComponentProps<typeof Dialog> & {
|
type SettingsDialogProps = React.ComponentProps<typeof Dialog> & {
|
||||||
defaultSection?: SettingsSection;
|
defaultSection?: SettingsSection;
|
||||||
@@ -43,6 +44,14 @@ export function SettingsDialog(props: SettingsDialogProps) {
|
|||||||
const [activeSection, setActiveSection] =
|
const [activeSection, setActiveSection] =
|
||||||
useState<SettingsSection>(defaultSection);
|
useState<SettingsSection>(defaultSection);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// When opening the dialog, ensure the active section follows the caller's intent.
|
||||||
|
// This allows triggers like "About" to open the dialog directly on that page.
|
||||||
|
if (dialogProps.open) {
|
||||||
|
setActiveSection(defaultSection);
|
||||||
|
}
|
||||||
|
}, [defaultSection, dialogProps.open]);
|
||||||
|
|
||||||
const sections = useMemo(
|
const sections = useMemo(
|
||||||
() => [
|
() => [
|
||||||
{
|
{
|
||||||
@@ -62,6 +71,7 @@ export function SettingsDialog(props: SettingsDialogProps) {
|
|||||||
},
|
},
|
||||||
{ id: "tools", label: t.settings.sections.tools, icon: WrenchIcon },
|
{ id: "tools", label: t.settings.sections.tools, icon: WrenchIcon },
|
||||||
{ id: "skills", label: t.settings.sections.skills, icon: SparklesIcon },
|
{ id: "skills", label: t.settings.sections.skills, icon: SparklesIcon },
|
||||||
|
{ id: "about", label: t.settings.sections.about, icon: InfoIcon },
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
t.settings.sections.appearance,
|
t.settings.sections.appearance,
|
||||||
@@ -69,6 +79,7 @@ export function SettingsDialog(props: SettingsDialogProps) {
|
|||||||
t.settings.sections.tools,
|
t.settings.sections.tools,
|
||||||
t.settings.sections.skills,
|
t.settings.sections.skills,
|
||||||
t.settings.sections.notification,
|
t.settings.sections.notification,
|
||||||
|
t.settings.sections.about,
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
@@ -122,7 +133,7 @@ export function SettingsDialog(props: SettingsDialogProps) {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{activeSection === "notification" && <NotificationSettingsPage />}
|
{activeSection === "notification" && <NotificationSettingsPage />}
|
||||||
{activeSection === "acknowledge" && <AcknowledgePage />}
|
{activeSection === "about" && <AboutSettingsPage />}
|
||||||
</div>
|
</div>
|
||||||
</ScrollArea>
|
</ScrollArea>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -32,11 +32,18 @@ import { SettingsDialog } from "./settings";
|
|||||||
|
|
||||||
export function WorkspaceNavMenu() {
|
export function WorkspaceNavMenu() {
|
||||||
const [settingsOpen, setSettingsOpen] = useState(false);
|
const [settingsOpen, setSettingsOpen] = useState(false);
|
||||||
|
const [settingsDefaultSection, setSettingsDefaultSection] = useState<
|
||||||
|
"appearance" | "memory" | "tools" | "skills" | "notification" | "about"
|
||||||
|
>("appearance");
|
||||||
const { open: isSidebarOpen } = useSidebar();
|
const { open: isSidebarOpen } = useSidebar();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<SettingsDialog open={settingsOpen} onOpenChange={setSettingsOpen} />
|
<SettingsDialog
|
||||||
|
open={settingsOpen}
|
||||||
|
onOpenChange={setSettingsOpen}
|
||||||
|
defaultSection={settingsDefaultSection}
|
||||||
|
/>
|
||||||
<SidebarMenu className="w-full">
|
<SidebarMenu className="w-full">
|
||||||
<SidebarMenuItem>
|
<SidebarMenuItem>
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
@@ -64,7 +71,12 @@ export function WorkspaceNavMenu() {
|
|||||||
sideOffset={4}
|
sideOffset={4}
|
||||||
>
|
>
|
||||||
<DropdownMenuGroup>
|
<DropdownMenuGroup>
|
||||||
<DropdownMenuItem onClick={() => setSettingsOpen(true)}>
|
<DropdownMenuItem
|
||||||
|
onClick={() => {
|
||||||
|
setSettingsDefaultSection("appearance");
|
||||||
|
setSettingsOpen(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
<Settings2Icon />
|
<Settings2Icon />
|
||||||
{t.common.settings}
|
{t.common.settings}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
@@ -108,7 +120,12 @@ export function WorkspaceNavMenu() {
|
|||||||
</a>
|
</a>
|
||||||
</DropdownMenuGroup>
|
</DropdownMenuGroup>
|
||||||
<DropdownMenuSeparator />
|
<DropdownMenuSeparator />
|
||||||
<DropdownMenuItem>
|
<DropdownMenuItem
|
||||||
|
onClick={() => {
|
||||||
|
setSettingsDefaultSection("about");
|
||||||
|
setSettingsOpen(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
<InfoIcon />
|
<InfoIcon />
|
||||||
{t.workspace.about}
|
{t.workspace.about}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
|
|||||||
@@ -209,7 +209,7 @@ export const enUS: Translations = {
|
|||||||
tools: "Tools",
|
tools: "Tools",
|
||||||
skills: "Skills",
|
skills: "Skills",
|
||||||
notification: "Notification",
|
notification: "Notification",
|
||||||
acknowledge: "Acknowledge",
|
about: "About",
|
||||||
},
|
},
|
||||||
memory: {
|
memory: {
|
||||||
title: "Memory",
|
title: "Memory",
|
||||||
|
|||||||
@@ -157,7 +157,7 @@ export interface Translations {
|
|||||||
tools: string;
|
tools: string;
|
||||||
skills: string;
|
skills: string;
|
||||||
notification: string;
|
notification: string;
|
||||||
acknowledge: string;
|
about: string;
|
||||||
};
|
};
|
||||||
memory: {
|
memory: {
|
||||||
title: string;
|
title: string;
|
||||||
|
|||||||
@@ -205,7 +205,7 @@ export const zhCN: Translations = {
|
|||||||
tools: "工具",
|
tools: "工具",
|
||||||
skills: "技能",
|
skills: "技能",
|
||||||
notification: "通知",
|
notification: "通知",
|
||||||
acknowledge: "致谢",
|
about: "关于",
|
||||||
},
|
},
|
||||||
memory: {
|
memory: {
|
||||||
title: "记忆",
|
title: "记忆",
|
||||||
|
|||||||
4
frontend/src/typings/md.d.ts
vendored
Normal file
4
frontend/src/typings/md.d.ts
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
declare module "*.md" {
|
||||||
|
const content: string;
|
||||||
|
export default content;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user