feat: enable investigation mode

This commit is contained in:
Li Xin
2025-04-30 19:53:14 +08:00
parent 3ef36b95f6
commit 0a0f705aca
6 changed files with 104 additions and 23 deletions

View File

@@ -13,8 +13,14 @@ import {
import { Button } from "~/components/ui/button";
import type { Option } from "~/core/messages";
import {
setEnableBackgroundInvestigation,
useSettingsStore,
} from "~/core/store";
import { cn } from "~/lib/utils";
import { Detective } from "../_icons/detective";
import { Tooltip } from "./tooltip";
export function InputBox({
@@ -37,6 +43,9 @@ export function InputBox({
const [message, setMessage] = useState("");
const [imeStatus, setImeStatus] = useState<"active" | "inactive">("inactive");
const [indent, setIndent] = useState(0);
const backgroundInvestigation = useSettingsStore(
(state) => state.general.enableBackgroundInvestigation,
);
const textareaRef = useRef<HTMLTextAreaElement>(null);
const feedbackRef = useRef<HTMLDivElement>(null);
@@ -137,7 +146,37 @@ export function InputBox({
/>
</div>
<div className="flex items-center px-4 py-2">
<div className="flex grow"></div>
<div className="flex grow">
<Tooltip
className="max-w-60"
title={
<div>
<h3 className="mb-2 font-bold">
Investigation Mode: {backgroundInvestigation ? "On" : "Off"}
</h3>
<p>
When enabled, DeerFlow will perform a quick search before
planning. This is useful for researches related to ongoing
events and news.
</p>
</div>
}
>
<Button
className={cn(
"rounded-2xl",
backgroundInvestigation && "!border-brand !text-brand",
)}
variant="outline"
size="lg"
onClick={() =>
setEnableBackgroundInvestigation(!backgroundInvestigation)
}
>
<Detective /> Investigation
</Button>
</Tooltip>
</div>
<div className="flex shrink-0 items-center gap-2">
<Tooltip title={responding ? "Stop" : "Send"}>
<Button

View File

@@ -0,0 +1,26 @@
export function Detective({ className }: { className?: string }) {
return (
<svg
className={className}
version="1.1"
width="800px"
height="800px"
viewBox="0 0 512 512"
>
<g fill="currentcolor">
<path
d="M392.692,257.322c-1.172-8.125-2.488-16.98-3.807-25.984c-5.856-39.012-12.59-81.688-14.86-87.832
c-4.318-11.715-18.371-44.723-68.217-25.984c-15.738,5.926-18.812,11.93-41.648,8.93c-17.273-2.27-28.326-15.59-52.336-24.668
c-49.844-18.883-71.584,11.711-75.902,23.422c-2.27,6.148-9.004,67.121-14.86,106.133c-1.39,8.86-2.633,17.566-3.804,25.621
c37.256,7.535,84.174,12.879,138.705,12.879C309.541,269.837,355.801,264.716,392.692,257.322z"
/>
<path
d="M443.707,306.509c-8.051-2.196-16.834-4.246-26.057-6.148c-1.83-0.805-3.66-1.535-5.49-2.27h-0.072
c-46.918,10.394-102.254,15.664-156.125,15.664c-53.652,0-108.768-5.27-155.541-15.516c-1.316,0.512-2.707,1.098-4.098,1.684
c-8.858,1.828-17.348,3.73-25.106,5.781l-0.148,0.074C27.008,317.49,0,333.372,0,350.939c0,36.012,114.549,65.289,256.035,65.289
c141.34,0,255.965-29.278,255.965-65.289C512,333.74,486.016,318.22,443.707,306.509z"
/>
</g>
</svg>
);
}

View File

@@ -124,21 +124,20 @@ function Jumbotron() {
flickerChance={0.12}
/>
<div className="relative z-10 flex flex-col items-center justify-center gap-12">
<h1 className="text-center text-6xl font-bold">
<h1 className="text-center text-4xl font-bold md:text-6xl">
<span className="bg-gradient-to-r from-white via-gray-200 to-gray-400 bg-clip-text text-transparent">
Deep Research{" "}
</span>
<AuroraText>at Your Fingertips</AuroraText>
</h1>
<p className="hidden max-w-4xl text-center text-2xl font-light opacity-75 md:block">
Discover the revolutionary Multi-Agent Research Assistant that
empowers you to dive deeper and wider into any subject. Equipped with
the powerful tools like search engines, crawlers, Python, and MCP
services, DeerFlow provides instant insights, in-depth reports and
even captivating podcasts.
<p className="max-w-4xl p-2 text-center text-sm font-light opacity-80 md:text-2xl">
Meet <span className="font-medium">DeerFlow</span>, your ultimate Deep
Research assistant. With powerful tools like search engines, web
crawlers, Python and MCP services, it provides instant insights,
comprehensive reports, or even captivating podcasts.
</p>
<div className="flex gap-6">
<Button className="w-42 text-lg" size="lg" asChild>
<Button className="hidden text-lg md:flex md:w-42" size="lg" asChild>
<Link href="/chat">
Get Started <ChevronRight />
</Link>
@@ -211,7 +210,7 @@ const caseStudies = [
function CaseStudySection() {
return (
<section className="relative container flex flex-col items-center justify-center">
<section className="relative container hidden flex-col items-center justify-center md:flex">
<SectionHeader
title="Case Studies"
description="See DeerFlow in action through replays."

View File

@@ -17,6 +17,7 @@ export async function* chatStream(
max_plan_iterations: number;
max_step_num: number;
interrupt_feedback?: string;
enable_background_investigation: boolean;
mcp_settings?: {
servers: Record<
string,

View File

@@ -10,6 +10,7 @@ const SETTINGS_KEY = "deerflow.settings";
const DEFAULT_SETTINGS: SettingsState = {
general: {
autoAcceptedPlan: false,
enableBackgroundInvestigation: false,
maxPlanIterations: 1,
maxStepNum: 3,
},
@@ -21,6 +22,7 @@ const DEFAULT_SETTINGS: SettingsState = {
export type SettingsState = {
general: {
autoAcceptedPlan: boolean;
enableBackgroundInvestigation: boolean;
maxPlanIterations: number;
maxStepNum: number;
};
@@ -48,9 +50,10 @@ export const loadSettings = () => {
const json = localStorage.getItem(SETTINGS_KEY);
if (json) {
const settings = JSON.parse(json);
for (const key in DEFAULT_SETTINGS) {
if (!(key in settings)) {
settings[key] = DEFAULT_SETTINGS[key as keyof SettingsState];
for (const key in DEFAULT_SETTINGS.general) {
if (!(key in settings.general)) {
settings.general[key as keyof SettingsState["general"]] =
DEFAULT_SETTINGS.general[key as keyof SettingsState["general"]];
}
}
@@ -71,14 +74,14 @@ export const saveSettings = () => {
export const getChatStreamSettings = () => {
let mcpSettings:
| {
servers: Record<
string,
MCPServerMetadata & {
enabled_tools: string[];
add_to_agents: string[];
}
>;
}
servers: Record<
string,
MCPServerMetadata & {
enabled_tools: string[];
add_to_agents: string[];
}
>;
}
| undefined = undefined;
const { mcp, general } = useSettingsStore.getState();
const mcpServers = mcp.servers.filter((server) => server.enabled);
@@ -120,4 +123,13 @@ export const getChatStreamSettings = () => {
};
};
export function setEnableBackgroundInvestigation(value: boolean) {
useSettingsStore.setState((state) => ({
general: {
...state.general,
enableBackgroundInvestigation: value,
},
}));
saveSettings();
}
loadSettings();

View File

@@ -50,7 +50,9 @@ export const useStore = create<{
}));
},
updateMessage(message: Message) {
set(state => ({ messages: new Map(state.messages).set(message.id, message) }));
set((state) => ({
messages: new Map(state.messages).set(message.id, message),
}));
},
updateMessages(messages: Message[]) {
set((state) => {
@@ -67,7 +69,7 @@ export const useStore = create<{
},
setOngoingResearch(researchId: string | null) {
set({ ongoingResearchId: researchId });
}
},
}));
export async function sendMessage(
@@ -96,6 +98,8 @@ export async function sendMessage(
thread_id: THREAD_ID,
interrupt_feedback: interruptFeedback,
auto_accepted_plan: settings.autoAcceptedPlan,
enable_background_investigation:
settings.enableBackgroundInvestigation ?? true,
max_plan_iterations: settings.maxPlanIterations,
max_step_num: settings.maxStepNum,
mcp_settings: settings.mcpSettings,