diff --git a/frontend/src/app/workspace/chats/[thread_id]/page.tsx b/frontend/src/app/workspace/chats/[thread_id]/page.tsx new file mode 100644 index 0000000..47faa64 --- /dev/null +++ b/frontend/src/app/workspace/chats/[thread_id]/page.tsx @@ -0,0 +1,123 @@ +"use client"; + +import { type HumanMessage } from "@langchain/core/messages"; +import { useStream } from "@langchain/langgraph-sdk/react"; +import { useQueryClient } from "@tanstack/react-query"; +import { useParams, useRouter } from "next/navigation"; +import { useCallback, useEffect, useMemo, useState } from "react"; + +import type { PromptInputMessage } from "@/components/ai-elements/prompt-input"; +import { BreadcrumbItem } from "@/components/ui/breadcrumb"; +import { InputBox } from "@/components/workspace/input-box"; +import { MessageList } from "@/components/workspace/message-list/message-list"; +import { + WorkspaceContainer, + WorkspaceBody, + WorkspaceHeader, + WorkspaceFooter, +} from "@/components/workspace/workspace-container"; +import { getLangGraphClient } from "@/core/api"; +import type { + AgentThread, + AgentThreadContext, + AgentThreadState, +} from "@/core/threads"; +import { titleOfThread } from "@/core/threads/utils"; +import { uuid } from "@/core/utils/uuid"; + +const langGraphClient = getLangGraphClient(); + +export default function ChatPage() { + const router = useRouter(); + const queryClient = useQueryClient(); + const { thread_id: threadIdFromPath } = useParams<{ thread_id: string }>(); + const isNewThread = useMemo( + () => threadIdFromPath === "new", + [threadIdFromPath], + ); + const [threadId, setThreadId] = useState(null); + const [threadContext, setThreadContext] = useState({ + thread_id: "", + model: "deepseek-v3.2", + thinking_enabled: true, + }); + useEffect(() => { + if (threadIdFromPath !== "new") { + setThreadId(threadIdFromPath); + } else { + setThreadId(uuid()); + } + }, [threadIdFromPath]); + const thread = useStream({ + client: langGraphClient, + assistantId: "lead_agent", + threadId: !isNewThread ? threadId : undefined, + reconnectOnMount: true, + fetchStateHistory: true, + onFinish() { + void queryClient.invalidateQueries({ queryKey: ["threads", "search"] }); + }, + }); + const handleSubmit = useCallback( + async (message: PromptInputMessage) => { + const text = message.text.trim(); + if (isNewThread) { + router.replace(`/workspace/chats/${threadId}`); + } + await thread.submit( + { + messages: [ + { + type: "human", + content: [ + { + type: "text", + text, + }, + ], + }, + ] as HumanMessage[], + }, + { + threadId: isNewThread ? threadId! : undefined, + streamSubgraphs: true, + streamResumable: true, + context: { + ...threadContext, + thread_id: threadId!, + }, + }, + ); + void queryClient.invalidateQueries({ queryKey: ["threads", "search"] }); + }, + [isNewThread, queryClient, router, thread, threadContext, threadId], + ); + const handleStop = useCallback(async () => { + await thread.stop(); + }, [thread]); + return ( + + + + {isNewThread + ? "New" + : titleOfThread(thread as unknown as AgentThread)} + + + +
+ +
+
+ + + +
+ ); +} diff --git a/frontend/src/app/workspace/chats/page.tsx b/frontend/src/app/workspace/chats/page.tsx new file mode 100644 index 0000000..1127faa --- /dev/null +++ b/frontend/src/app/workspace/chats/page.tsx @@ -0,0 +1,18 @@ +"use client"; + +import { + WorkspaceBody, + WorkspaceContainer, + WorkspaceHeader, +} from "@/components/workspace/workspace-container"; + +export default function ChatsPage() { + return ( + + + +
+
+
+ ); +} diff --git a/frontend/src/app/workspace/threads/[thread_id]/page.tsx b/frontend/src/app/workspace/threads/[thread_id]/page.tsx deleted file mode 100644 index 4562f83..0000000 --- a/frontend/src/app/workspace/threads/[thread_id]/page.tsx +++ /dev/null @@ -1,26 +0,0 @@ -"use client"; - -import { useStream } from "@langchain/langgraph-sdk/react"; -import { useParams } from "next/navigation"; - -import { getLangGraphClient } from "@/core/api"; -import type { AgentThreadState } from "@/core/threads"; - -const apiClient = getLangGraphClient(); - -export default function TestPage() { - const { thread_id: threadId } = useParams<{ thread_id: string }>(); - const thread = useStream({ - client: apiClient, - assistantId: "lead_agent", - threadId, - reconnectOnMount: true, - fetchStateHistory: true, - }); - return ( -
-
{threadId}
-
{thread.isLoading ? "loading" : "not loading"}
-
- ); -}