refactor: refine folder structure and rename

This commit is contained in:
Henry Li
2026-01-16 09:13:02 +08:00
parent 61499624a0
commit e9846c1dda
13 changed files with 65 additions and 37 deletions

View File

@@ -17,8 +17,12 @@ import {
WorkspaceFooter,
} from "@/components/workspace/workspace-container";
import { getLangGraphClient } from "@/core/api";
import type { MessageThread, MessageThreadState } from "@/core/thread";
import { titleOfThread } from "@/core/thread/utils";
import type {
AgentThread,
AgentThreadContext,
AgentThreadState,
} from "@/core/threads";
import { titleOfThread } from "@/core/threads/utils";
import { uuid } from "@/core/utils/uuid";
const langGraphClient = getLangGraphClient();
@@ -32,6 +36,11 @@ export default function ChatPage() {
[threadIdFromPath],
);
const [threadId, setThreadId] = useState<string | null>(null);
const [threadContext, setThreadContext] = useState<AgentThreadContext>({
thread_id: "",
model: "deepseek-v3.2",
thinking_enabled: true,
});
useEffect(() => {
if (threadIdFromPath !== "new") {
setThreadId(threadIdFromPath);
@@ -39,7 +48,7 @@ export default function ChatPage() {
setThreadId(uuid());
}
}, [threadIdFromPath]);
const thread = useStream<MessageThreadState>({
const thread = useStream<AgentThreadState>({
client: langGraphClient,
assistantId: "lead_agent",
threadId: !isNewThread ? threadId : undefined,
@@ -74,15 +83,14 @@ export default function ChatPage() {
streamSubgraphs: true,
streamResumable: true,
context: {
...threadContext,
thread_id: threadId!,
model: "deepseek-v3.2",
thinking_enabled: true,
},
},
);
void queryClient.invalidateQueries({ queryKey: ["threads", "search"] });
},
[isNewThread, queryClient, router, thread, threadId],
[isNewThread, queryClient, router, thread, threadContext, threadId],
);
const handleStop = useCallback(async () => {
await thread.stop();
@@ -93,7 +101,7 @@ export default function ChatPage() {
<BreadcrumbItem className="hidden md:block">
{isNewThread
? "New"
: titleOfThread(thread as unknown as MessageThread)}
: titleOfThread(thread as unknown as AgentThread)}
</BreadcrumbItem>
</WorkspaceHeader>
<WorkspaceBody>

View File

@@ -4,13 +4,13 @@ import { useStream } from "@langchain/langgraph-sdk/react";
import { useParams } from "next/navigation";
import { getLangGraphClient } from "@/core/api";
import type { MessageThreadState } from "@/core/thread";
import type { AgentThreadState } from "@/core/threads";
const apiClient = getLangGraphClient();
export default function TestPage() {
const { thread_id: threadId } = useParams<{ thread_id: string }>();
const thread = useStream<MessageThreadState>({
const thread = useStream<AgentThreadState>({
client: apiClient,
assistantId: "lead_agent",
threadId,

View File

@@ -1,9 +1,11 @@
import type { ChatStatus } from "ai";
import { LightbulbIcon, LightbulbOffIcon } from "lucide-react";
import { useCallback, type ComponentProps } from "react";
import {
PromptInput,
PromptInputBody,
PromptInputButton,
PromptInputFooter,
PromptInputSubmit,
PromptInputTextarea,
@@ -11,6 +13,8 @@ import {
} from "@/components/ai-elements/prompt-input";
import { cn } from "@/lib/utils";
import { Tooltip } from "./tooltip";
export function InputBox({
className,
autoFocus,
@@ -57,7 +61,13 @@ export function InputBox({
/>
</PromptInputBody>
<PromptInputFooter className="flex">
<div></div>
<div>
<Tooltip content="">
<PromptInputButton>
<LightbulbOffIcon className="size-4" />
</PromptInputButton>
</Tooltip>
</div>
<div className="flex items-center gap-2">
<PromptInputSubmit
className="rounded-full"

View File

@@ -21,14 +21,13 @@ import {
ChainOfThoughtStep,
} from "@/components/ai-elements/chain-of-thought";
import { MessageResponse } from "@/components/ai-elements/message";
import { useRehypeSplitWordsIntoSpans } from "@/core/rehype";
import { extractTitleFromMarkdown } from "@/core/utils/markdown";
import { cn } from "@/lib/utils";
import {
extractReasoningContentFromMessage,
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({
className,

View File

@@ -6,11 +6,15 @@ import {
MessageContent as AIElementMessageContent,
MessageResponse as AIElementMessageResponse,
} from "@/components/ai-elements/message";
import {
extractContentFromMessage,
hasReasoning,
hasToolCalls,
} from "@/core/messages/utils";
import { useRehypeSplitWordsIntoSpans } from "@/core/rehype";
import { cn } from "@/lib/utils";
import { MessageGroup } from "./message-group";
import { extractContentFromMessage, hasReasoning, hasToolCalls } from "./utils";
export function MessageListItem({
className,

View File

@@ -5,7 +5,8 @@ import {
ConversationContent,
ConversationScrollButton,
} 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 { StreamingIndicator } from "../streaming-indicator";
@@ -13,14 +14,13 @@ import { StreamingIndicator } from "../streaming-indicator";
import { MessageGroup } from "./message-group";
import { MessageListItem } from "./message-list-item";
import { MessageListSkeleton } from "./skeleton";
import { groupMessages, hasContent } from "./utils";
export function MessageList({
className,
thread,
}: {
className?: string;
thread: UseStream<MessageThreadState>;
thread: UseStream<AgentThreadState>;
}) {
if (thread.isThreadLoading) {
return <MessageListSkeleton />;

View File

@@ -21,7 +21,7 @@ import {
SidebarMenuItem,
} from "@/components/ui/sidebar";
import { useDeleteThread, useThreads } from "@/core/api";
import { pathOfThread, titleOfThread } from "@/core/thread/utils";
import { pathOfThread, titleOfThread } from "@/core/threads/utils";
export function RecentChatList() {
const router = useRouter();

View File

@@ -1,7 +1,7 @@
import type { ThreadsClient } from "@langchain/langgraph-sdk/client";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import type { MessageThread, MessageThreadState } from "../thread";
import type { AgentThread, AgentThreadState } from "../threads";
import { getLangGraphClient } from "./client";
@@ -13,12 +13,12 @@ export function useThreads(
},
) {
const langGraphClient = getLangGraphClient();
return useQuery<MessageThread[]>({
return useQuery<AgentThread[]>({
queryKey: ["threads", "search", params],
queryFn: async () => {
const response =
await langGraphClient.threads.search<MessageThreadState>(params);
return response as MessageThread[];
await langGraphClient.threads.search<AgentThreadState>(params);
return response as AgentThread[];
},
});
}
@@ -36,7 +36,7 @@ export function useDeleteThread() {
queryKey: ["threads", "search"],
exact: false,
},
(oldData: Array<MessageThread>) => {
(oldData: Array<AgentThread>) => {
return oldData.filter((t) => t.thread_id !== threadId);
},
);

View File

@@ -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> {}

View 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;
}

View File

@@ -1,8 +1,8 @@
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) {
return `/workspace/chats/${thread.thread_id}`;
}
@@ -19,9 +19,9 @@ export function textOfMessage(message: BaseMessage) {
return null;
}
export function titleOfThread(thread: MessageThread) {
export function titleOfThread(thread: AgentThread) {
if (thread.values && "title" in thread.values) {
return thread.values.title as string;
return thread.values.title;
}
return "Untitled";
}