diff --git a/frontend/src/app/workspace/agents/[agent_name]/chats/[thread_id]/page.tsx b/frontend/src/app/workspace/agents/[agent_name]/chats/[thread_id]/page.tsx index 0a5236d..a44ad3f 100644 --- a/frontend/src/app/workspace/agents/[agent_name]/chats/[thread_id]/page.tsx +++ b/frontend/src/app/workspace/agents/[agent_name]/chats/[thread_id]/page.tsx @@ -43,6 +43,7 @@ export default function AgentChatPage() { context: { ...settings.context, agent_name: agent_name }, onStart: () => { setIsNewThread(false); + // ! Important: Never use next.js router for navigation in this case, otherwise it will cause the thread to re-mount and lose all states. Use native history API instead. history.replaceState( null, "", diff --git a/frontend/src/app/workspace/chats/[thread_id]/layout.tsx b/frontend/src/app/workspace/chats/[thread_id]/layout.tsx index 1270b8e..8771037 100644 --- a/frontend/src/app/workspace/chats/[thread_id]/layout.tsx +++ b/frontend/src/app/workspace/chats/[thread_id]/layout.tsx @@ -1,8 +1,5 @@ "use client"; -import { useParams } from "next/navigation"; -import { useEffect, useRef, useState } from "react"; - import { PromptInputProvider } from "@/components/ai-elements/prompt-input"; import { ArtifactsProvider } from "@/components/workspace/artifacts"; import { SubtasksProvider } from "@/core/tasks/context"; @@ -12,24 +9,8 @@ export default function ChatLayout({ }: { children: React.ReactNode; }) { - const { thread_id } = useParams<{ thread_id: string }>(); - const prevThreadId = useRef(thread_id); - - // Increment only when navigating TO "new" from a non-"new" route. - // This forces a full remount of the subtree for a fresh new-chat state, - // without remounting when the URL transitions from "new" → actual-id - // (which would interrupt streaming). - const [generation, setGeneration] = useState(0); - - useEffect(() => { - if (thread_id === "new" && prevThreadId.current !== "new") { - setGeneration((g) => g + 1); - } - prevThreadId.current = thread_id; - }, [thread_id]); - return ( - + {children} diff --git a/frontend/src/app/workspace/chats/[thread_id]/page.tsx b/frontend/src/app/workspace/chats/[thread_id]/page.tsx index 0bc0225..3147358 100644 --- a/frontend/src/app/workspace/chats/[thread_id]/page.tsx +++ b/frontend/src/app/workspace/chats/[thread_id]/page.tsx @@ -1,6 +1,5 @@ "use client"; -import { useRouter } from "next/navigation"; import { useCallback } from "react"; import { type PromptInputMessage } from "@/components/ai-elements/prompt-input"; @@ -26,7 +25,6 @@ import { cn } from "@/lib/utils"; export default function ChatPage() { const { t } = useI18n(); - const router = useRouter(); const [settings, setSettings] = useLocalSettings(); const { threadId, isNewThread, setIsNewThread, isMock } = useThreadChat(); @@ -40,11 +38,8 @@ export default function ChatPage() { isMock, onStart: () => { setIsNewThread(false); - // Use router.replace so Next.js Router's internal state is updated. - // This ensures subsequent "New Chat" clicks are treated as a real - // cross-route navigation (actual-id → "new") rather than a no-op - // same-path navigation, which was causing stale content to persist. - router.replace(`/workspace/chats/${threadId}`); + // ! Important: Never use next.js router for navigation in this case, otherwise it will cause the thread to re-mount and lose all states. Use native history API instead. + history.replaceState(null, "", `/workspace/chats/${threadId}`); }, onFinish: (state) => { if (document.hidden || !document.hasFocus()) {