mirror of
https://gitee.com/wanwujie/deer-flow
synced 2026-04-19 12:24:46 +08:00
refactor: refine folder structure and rename
This commit is contained in:
@@ -17,8 +17,12 @@ import {
|
|||||||
WorkspaceFooter,
|
WorkspaceFooter,
|
||||||
} from "@/components/workspace/workspace-container";
|
} from "@/components/workspace/workspace-container";
|
||||||
import { getLangGraphClient } from "@/core/api";
|
import { getLangGraphClient } from "@/core/api";
|
||||||
import type { MessageThread, MessageThreadState } from "@/core/thread";
|
import type {
|
||||||
import { titleOfThread } from "@/core/thread/utils";
|
AgentThread,
|
||||||
|
AgentThreadContext,
|
||||||
|
AgentThreadState,
|
||||||
|
} from "@/core/threads";
|
||||||
|
import { titleOfThread } from "@/core/threads/utils";
|
||||||
import { uuid } from "@/core/utils/uuid";
|
import { uuid } from "@/core/utils/uuid";
|
||||||
|
|
||||||
const langGraphClient = getLangGraphClient();
|
const langGraphClient = getLangGraphClient();
|
||||||
@@ -32,6 +36,11 @@ export default function ChatPage() {
|
|||||||
[threadIdFromPath],
|
[threadIdFromPath],
|
||||||
);
|
);
|
||||||
const [threadId, setThreadId] = useState<string | null>(null);
|
const [threadId, setThreadId] = useState<string | null>(null);
|
||||||
|
const [threadContext, setThreadContext] = useState<AgentThreadContext>({
|
||||||
|
thread_id: "",
|
||||||
|
model: "deepseek-v3.2",
|
||||||
|
thinking_enabled: true,
|
||||||
|
});
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (threadIdFromPath !== "new") {
|
if (threadIdFromPath !== "new") {
|
||||||
setThreadId(threadIdFromPath);
|
setThreadId(threadIdFromPath);
|
||||||
@@ -39,7 +48,7 @@ export default function ChatPage() {
|
|||||||
setThreadId(uuid());
|
setThreadId(uuid());
|
||||||
}
|
}
|
||||||
}, [threadIdFromPath]);
|
}, [threadIdFromPath]);
|
||||||
const thread = useStream<MessageThreadState>({
|
const thread = useStream<AgentThreadState>({
|
||||||
client: langGraphClient,
|
client: langGraphClient,
|
||||||
assistantId: "lead_agent",
|
assistantId: "lead_agent",
|
||||||
threadId: !isNewThread ? threadId : undefined,
|
threadId: !isNewThread ? threadId : undefined,
|
||||||
@@ -74,15 +83,14 @@ export default function ChatPage() {
|
|||||||
streamSubgraphs: true,
|
streamSubgraphs: true,
|
||||||
streamResumable: true,
|
streamResumable: true,
|
||||||
context: {
|
context: {
|
||||||
|
...threadContext,
|
||||||
thread_id: threadId!,
|
thread_id: threadId!,
|
||||||
model: "deepseek-v3.2",
|
|
||||||
thinking_enabled: true,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
void queryClient.invalidateQueries({ queryKey: ["threads", "search"] });
|
void queryClient.invalidateQueries({ queryKey: ["threads", "search"] });
|
||||||
},
|
},
|
||||||
[isNewThread, queryClient, router, thread, threadId],
|
[isNewThread, queryClient, router, thread, threadContext, threadId],
|
||||||
);
|
);
|
||||||
const handleStop = useCallback(async () => {
|
const handleStop = useCallback(async () => {
|
||||||
await thread.stop();
|
await thread.stop();
|
||||||
@@ -93,7 +101,7 @@ export default function ChatPage() {
|
|||||||
<BreadcrumbItem className="hidden md:block">
|
<BreadcrumbItem className="hidden md:block">
|
||||||
{isNewThread
|
{isNewThread
|
||||||
? "New"
|
? "New"
|
||||||
: titleOfThread(thread as unknown as MessageThread)}
|
: titleOfThread(thread as unknown as AgentThread)}
|
||||||
</BreadcrumbItem>
|
</BreadcrumbItem>
|
||||||
</WorkspaceHeader>
|
</WorkspaceHeader>
|
||||||
<WorkspaceBody>
|
<WorkspaceBody>
|
||||||
|
|||||||
@@ -4,13 +4,13 @@ import { useStream } from "@langchain/langgraph-sdk/react";
|
|||||||
import { useParams } from "next/navigation";
|
import { useParams } from "next/navigation";
|
||||||
|
|
||||||
import { getLangGraphClient } from "@/core/api";
|
import { getLangGraphClient } from "@/core/api";
|
||||||
import type { MessageThreadState } from "@/core/thread";
|
import type { AgentThreadState } from "@/core/threads";
|
||||||
|
|
||||||
const apiClient = getLangGraphClient();
|
const apiClient = getLangGraphClient();
|
||||||
|
|
||||||
export default function TestPage() {
|
export default function TestPage() {
|
||||||
const { thread_id: threadId } = useParams<{ thread_id: string }>();
|
const { thread_id: threadId } = useParams<{ thread_id: string }>();
|
||||||
const thread = useStream<MessageThreadState>({
|
const thread = useStream<AgentThreadState>({
|
||||||
client: apiClient,
|
client: apiClient,
|
||||||
assistantId: "lead_agent",
|
assistantId: "lead_agent",
|
||||||
threadId,
|
threadId,
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
import type { ChatStatus } from "ai";
|
import type { ChatStatus } from "ai";
|
||||||
|
import { LightbulbIcon, LightbulbOffIcon } from "lucide-react";
|
||||||
import { useCallback, type ComponentProps } from "react";
|
import { useCallback, type ComponentProps } from "react";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
PromptInput,
|
PromptInput,
|
||||||
PromptInputBody,
|
PromptInputBody,
|
||||||
|
PromptInputButton,
|
||||||
PromptInputFooter,
|
PromptInputFooter,
|
||||||
PromptInputSubmit,
|
PromptInputSubmit,
|
||||||
PromptInputTextarea,
|
PromptInputTextarea,
|
||||||
@@ -11,6 +13,8 @@ import {
|
|||||||
} from "@/components/ai-elements/prompt-input";
|
} from "@/components/ai-elements/prompt-input";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
|
import { Tooltip } from "./tooltip";
|
||||||
|
|
||||||
export function InputBox({
|
export function InputBox({
|
||||||
className,
|
className,
|
||||||
autoFocus,
|
autoFocus,
|
||||||
@@ -57,7 +61,13 @@ export function InputBox({
|
|||||||
/>
|
/>
|
||||||
</PromptInputBody>
|
</PromptInputBody>
|
||||||
<PromptInputFooter className="flex">
|
<PromptInputFooter className="flex">
|
||||||
<div></div>
|
<div>
|
||||||
|
<Tooltip content="">
|
||||||
|
<PromptInputButton>
|
||||||
|
<LightbulbOffIcon className="size-4" />
|
||||||
|
</PromptInputButton>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<PromptInputSubmit
|
<PromptInputSubmit
|
||||||
className="rounded-full"
|
className="rounded-full"
|
||||||
|
|||||||
@@ -21,14 +21,13 @@ import {
|
|||||||
ChainOfThoughtStep,
|
ChainOfThoughtStep,
|
||||||
} from "@/components/ai-elements/chain-of-thought";
|
} from "@/components/ai-elements/chain-of-thought";
|
||||||
import { MessageResponse } from "@/components/ai-elements/message";
|
import { MessageResponse } from "@/components/ai-elements/message";
|
||||||
import { useRehypeSplitWordsIntoSpans } from "@/core/rehype";
|
|
||||||
import { extractTitleFromMarkdown } from "@/core/utils/markdown";
|
|
||||||
import { cn } from "@/lib/utils";
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
extractReasoningContentFromMessage,
|
extractReasoningContentFromMessage,
|
||||||
findToolCallResult,
|
findToolCallResult,
|
||||||
} from "./utils";
|
} from "@/core/messages/utils";
|
||||||
|
import { useRehypeSplitWordsIntoSpans } from "@/core/rehype";
|
||||||
|
import { extractTitleFromMarkdown } from "@/core/utils/markdown";
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
export function MessageGroup({
|
export function MessageGroup({
|
||||||
className,
|
className,
|
||||||
|
|||||||
@@ -6,11 +6,15 @@ import {
|
|||||||
MessageContent as AIElementMessageContent,
|
MessageContent as AIElementMessageContent,
|
||||||
MessageResponse as AIElementMessageResponse,
|
MessageResponse as AIElementMessageResponse,
|
||||||
} from "@/components/ai-elements/message";
|
} from "@/components/ai-elements/message";
|
||||||
|
import {
|
||||||
|
extractContentFromMessage,
|
||||||
|
hasReasoning,
|
||||||
|
hasToolCalls,
|
||||||
|
} from "@/core/messages/utils";
|
||||||
import { useRehypeSplitWordsIntoSpans } from "@/core/rehype";
|
import { useRehypeSplitWordsIntoSpans } from "@/core/rehype";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
import { MessageGroup } from "./message-group";
|
import { MessageGroup } from "./message-group";
|
||||||
import { extractContentFromMessage, hasReasoning, hasToolCalls } from "./utils";
|
|
||||||
|
|
||||||
export function MessageListItem({
|
export function MessageListItem({
|
||||||
className,
|
className,
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ import {
|
|||||||
ConversationContent,
|
ConversationContent,
|
||||||
ConversationScrollButton,
|
ConversationScrollButton,
|
||||||
} from "@/components/ai-elements/conversation";
|
} from "@/components/ai-elements/conversation";
|
||||||
import type { MessageThreadState } from "@/core/thread";
|
import { groupMessages, hasContent } from "@/core/messages/utils";
|
||||||
|
import type { AgentThreadState } from "@/core/threads";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
import { StreamingIndicator } from "../streaming-indicator";
|
import { StreamingIndicator } from "../streaming-indicator";
|
||||||
@@ -13,14 +14,13 @@ import { StreamingIndicator } from "../streaming-indicator";
|
|||||||
import { MessageGroup } from "./message-group";
|
import { MessageGroup } from "./message-group";
|
||||||
import { MessageListItem } from "./message-list-item";
|
import { MessageListItem } from "./message-list-item";
|
||||||
import { MessageListSkeleton } from "./skeleton";
|
import { MessageListSkeleton } from "./skeleton";
|
||||||
import { groupMessages, hasContent } from "./utils";
|
|
||||||
|
|
||||||
export function MessageList({
|
export function MessageList({
|
||||||
className,
|
className,
|
||||||
thread,
|
thread,
|
||||||
}: {
|
}: {
|
||||||
className?: string;
|
className?: string;
|
||||||
thread: UseStream<MessageThreadState>;
|
thread: UseStream<AgentThreadState>;
|
||||||
}) {
|
}) {
|
||||||
if (thread.isThreadLoading) {
|
if (thread.isThreadLoading) {
|
||||||
return <MessageListSkeleton />;
|
return <MessageListSkeleton />;
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import {
|
|||||||
SidebarMenuItem,
|
SidebarMenuItem,
|
||||||
} from "@/components/ui/sidebar";
|
} from "@/components/ui/sidebar";
|
||||||
import { useDeleteThread, useThreads } from "@/core/api";
|
import { useDeleteThread, useThreads } from "@/core/api";
|
||||||
import { pathOfThread, titleOfThread } from "@/core/thread/utils";
|
import { pathOfThread, titleOfThread } from "@/core/threads/utils";
|
||||||
|
|
||||||
export function RecentChatList() {
|
export function RecentChatList() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import type { ThreadsClient } from "@langchain/langgraph-sdk/client";
|
import type { ThreadsClient } from "@langchain/langgraph-sdk/client";
|
||||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||||
|
|
||||||
import type { MessageThread, MessageThreadState } from "../thread";
|
import type { AgentThread, AgentThreadState } from "../threads";
|
||||||
|
|
||||||
import { getLangGraphClient } from "./client";
|
import { getLangGraphClient } from "./client";
|
||||||
|
|
||||||
@@ -13,12 +13,12 @@ export function useThreads(
|
|||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
const langGraphClient = getLangGraphClient();
|
const langGraphClient = getLangGraphClient();
|
||||||
return useQuery<MessageThread[]>({
|
return useQuery<AgentThread[]>({
|
||||||
queryKey: ["threads", "search", params],
|
queryKey: ["threads", "search", params],
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
const response =
|
const response =
|
||||||
await langGraphClient.threads.search<MessageThreadState>(params);
|
await langGraphClient.threads.search<AgentThreadState>(params);
|
||||||
return response as MessageThread[];
|
return response as AgentThread[];
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -36,7 +36,7 @@ export function useDeleteThread() {
|
|||||||
queryKey: ["threads", "search"],
|
queryKey: ["threads", "search"],
|
||||||
exact: false,
|
exact: false,
|
||||||
},
|
},
|
||||||
(oldData: Array<MessageThread>) => {
|
(oldData: Array<AgentThread>) => {
|
||||||
return oldData.filter((t) => t.thread_id !== threadId);
|
return oldData.filter((t) => t.thread_id !== threadId);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
import { type BaseMessage } from "@langchain/core/messages";
|
|
||||||
import type { Thread } from "@langchain/langgraph-sdk";
|
|
||||||
|
|
||||||
export interface MessageThreadState extends Record<string, unknown> {
|
|
||||||
messages: BaseMessage[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface MessageThread extends Thread<MessageThreadState> {}
|
|
||||||
15
frontend/src/core/threads/types.ts
Normal file
15
frontend/src/core/threads/types.ts
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import { type BaseMessage } from "@langchain/core/messages";
|
||||||
|
import type { Thread } from "@langchain/langgraph-sdk";
|
||||||
|
|
||||||
|
export interface AgentThreadState extends Record<string, unknown> {
|
||||||
|
title: string;
|
||||||
|
messages: BaseMessage[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AgentThread extends Thread<AgentThreadState> {}
|
||||||
|
|
||||||
|
export interface AgentThreadContext extends Record<string, unknown> {
|
||||||
|
thread_id: string;
|
||||||
|
model: string;
|
||||||
|
thinking_enabled: boolean;
|
||||||
|
}
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
import type { BaseMessage } from "@langchain/core/messages";
|
import type { BaseMessage } from "@langchain/core/messages";
|
||||||
|
|
||||||
import type { MessageThread } from "./types";
|
import type { AgentThread } from "./types";
|
||||||
|
|
||||||
export function pathOfThread(thread: MessageThread, includeAssistantId = true) {
|
export function pathOfThread(thread: AgentThread, includeAssistantId = true) {
|
||||||
if (includeAssistantId) {
|
if (includeAssistantId) {
|
||||||
return `/workspace/chats/${thread.thread_id}`;
|
return `/workspace/chats/${thread.thread_id}`;
|
||||||
}
|
}
|
||||||
@@ -19,9 +19,9 @@ export function textOfMessage(message: BaseMessage) {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function titleOfThread(thread: MessageThread) {
|
export function titleOfThread(thread: AgentThread) {
|
||||||
if (thread.values && "title" in thread.values) {
|
if (thread.values && "title" in thread.values) {
|
||||||
return thread.values.title as string;
|
return thread.values.title;
|
||||||
}
|
}
|
||||||
return "Untitled";
|
return "Untitled";
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user