fix:修复了thread_id会读到new的错误
This commit is contained in:
parent
ce4b0dcd4d
commit
081adb34b3
|
|
@ -1,7 +1,7 @@
|
|||
"use client";
|
||||
|
||||
import { FilesIcon, ListTodoIcon, XIcon } from "lucide-react";
|
||||
import { useSearchParams } from "next/navigation";
|
||||
import { useRouter, useSearchParams } from "next/navigation";
|
||||
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||
|
||||
import { ConversationEmptyState } from "@/components/ai-elements/conversation";
|
||||
|
|
@ -44,6 +44,7 @@ export default function ChatPage() {
|
|||
useSpecificChatMode();
|
||||
const [settings, setSettings] = useLocalSettings();
|
||||
const { setOpen: setSidebarOpen } = useSidebar();
|
||||
const router = useRouter();
|
||||
const {
|
||||
artifacts,
|
||||
open: artifactsOpen,
|
||||
|
|
@ -51,9 +52,12 @@ export default function ChatPage() {
|
|||
setArtifacts,
|
||||
select: selectArtifact,
|
||||
selectedArtifact,
|
||||
deselect: deselectArtifact,
|
||||
setFullscreen: setArtifactsFullscreen,
|
||||
fullscreen,
|
||||
} = useArtifacts();
|
||||
const { threadId, isNewThread, setIsNewThread, isMock } = useThreadChat();
|
||||
|
||||
const searchParams = useSearchParams();
|
||||
// History render rules:
|
||||
// - /workspace/chats/{thread_id}: always render history
|
||||
|
|
@ -63,8 +67,9 @@ export default function ChatPage() {
|
|||
searchParams.get("xclaw_used")?.trim().toLowerCase() === "true";
|
||||
|
||||
// Submission strategy:
|
||||
// - isnew=false + thread_id: reuse existing thread (explicit request from URL)
|
||||
// - xclaw_used=true: follow `isnew` (isnew=false => reuse existing thread)
|
||||
// - xclaw_used!=true: always create/start a new session (no history)
|
||||
// - otherwise: create/start a new session (no history)
|
||||
const createNewSession = useMemo(() => {
|
||||
if (!isNewThread) {
|
||||
return false;
|
||||
|
|
@ -99,7 +104,8 @@ export default function ChatPage() {
|
|||
isMock,
|
||||
onStart: (currentThreadId) => {
|
||||
setIsNewThread(false);
|
||||
history.replaceState(null, "", pathOfThread(currentThreadId));
|
||||
// Keep /new in history so router.back() can return to it.
|
||||
history.pushState(null, "", pathOfThread(currentThreadId));
|
||||
},
|
||||
onFinish: (state) => {
|
||||
if (document.hidden || !document.hasFocus()) {
|
||||
|
|
@ -205,6 +211,22 @@ export default function ChatPage() {
|
|||
await thread.stop();
|
||||
}, [thread]);
|
||||
|
||||
const resetNewSessionState = useCallback(() => {
|
||||
setIsNewThread(true);
|
||||
setHasSubmitted(false);
|
||||
setHistoryCutoff(null);
|
||||
setArtifacts([]);
|
||||
deselectArtifact();
|
||||
setArtifactsOpen(false);
|
||||
setArtifactsFullscreen(false);
|
||||
}, [
|
||||
deselectArtifact,
|
||||
setArtifacts,
|
||||
setArtifactsFullscreen,
|
||||
setArtifactsOpen,
|
||||
setIsNewThread,
|
||||
]);
|
||||
|
||||
return (
|
||||
<ThreadContext.Provider value={{ thread }}>
|
||||
<div
|
||||
|
|
@ -474,8 +496,15 @@ export default function ChatPage() {
|
|||
type: POST_MESSAGE_TYPES.XCLAW_USED,
|
||||
XClawUsed: false,
|
||||
});
|
||||
// 使用完整页面刷新确保组件重新挂载,isNewThread 为 true
|
||||
window.location.reload();
|
||||
resetNewSessionState();
|
||||
// 因为threadId可能为undefined,所以这里不直接导航到 /workspace/chats/new,而是通过 replace 的方式更新 URL 参数,保持在当前页面,触发 useThreadChat 重新计算状态。
|
||||
const nextQuery = new URLSearchParams();
|
||||
nextQuery.set("isnew", "false");
|
||||
nextQuery.set("xclaw_used", "false");
|
||||
if (threadId && threadId !== "new") {
|
||||
nextQuery.set("thread_id", threadId);
|
||||
}
|
||||
router.replace(`/workspace/chats/new?${nextQuery.toString()}`);
|
||||
}}
|
||||
>
|
||||
确定
|
||||
|
|
@ -513,7 +542,7 @@ export default function ChatPage() {
|
|||
</DevDialog>
|
||||
|
||||
{/* MARK: 开发测试:iframe 通信功能测试面板 */}
|
||||
{process.env.NODE_ENV !== "production" && <IframeTestPanel />}
|
||||
{/* {process.env.NODE_ENV !== "production" && <IframeTestPanel />} */}
|
||||
</div>
|
||||
</ThreadContext.Provider>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -4,24 +4,64 @@ import { useParams, usePathname, useRouter, useSearchParams } from "next/navigat
|
|||
import { useEffect, useState } from "react";
|
||||
|
||||
export function useThreadChat() {
|
||||
const { thread_id: threadIdFromPath } = useParams<{ thread_id: string }>();
|
||||
const pathname = usePathname();
|
||||
const router = useRouter();
|
||||
const params = useParams<{ thread_id?: string }>();
|
||||
const threadIdFromPathname = (() => {
|
||||
const parts = pathname.split("?")[0]?.split("/") ?? [];
|
||||
const idx = parts.lastIndexOf("chats");
|
||||
if (idx >= 0 && parts.length > idx + 1) {
|
||||
return parts[idx + 1];
|
||||
}
|
||||
return undefined;
|
||||
})();
|
||||
const threadIdFromPath = params?.thread_id !== 'new' ? params?.thread_id : threadIdFromPathname;
|
||||
console.log("[useThreadChat] pathname", pathname);
|
||||
console.log("[useThreadChat] params.thread_id", params?.thread_id);
|
||||
console.log("[useThreadChat] threadIdFromPathname", threadIdFromPathname);
|
||||
console.log("[useThreadChat] threadIdFromPath", threadIdFromPath);
|
||||
const readStoredThreadId = () => {
|
||||
if (typeof window === "undefined") {
|
||||
return undefined;
|
||||
}
|
||||
const stored = window.sessionStorage.getItem("workspace.thread_id");
|
||||
return stored && stored !== "new" ? stored : undefined;
|
||||
};
|
||||
|
||||
const searchParams = useSearchParams();
|
||||
const readQueryThreadId = () => {
|
||||
const fromHook = searchParams.get("thread_id")?.trim();
|
||||
if (fromHook && fromHook !== "new") {
|
||||
return fromHook;
|
||||
}
|
||||
if (typeof window === "undefined") {
|
||||
return undefined;
|
||||
}
|
||||
const fromLocation = new URLSearchParams(window.location.search).get(
|
||||
"thread_id",
|
||||
);
|
||||
if (fromLocation && fromLocation !== "new") {
|
||||
return fromLocation.trim();
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
const queryThreadIdFromParams = readQueryThreadId();
|
||||
console.log("[useThreadChat] query.thread_id", queryThreadIdFromParams);
|
||||
const normalizeThreadId = (value?: string | null) => {
|
||||
if (!value) {
|
||||
return undefined;
|
||||
}
|
||||
return value === "new" ? queryThreadIdFromParams : value;
|
||||
};
|
||||
const xClawUsedFromQuery = searchParams.get("xclaw_used");
|
||||
const isNewFromQuery =
|
||||
searchParams.get("isnew")?.trim().toLowerCase() === "false";
|
||||
const queryThreadIdFromParams = searchParams.get("thread_id")?.trim();
|
||||
const shouldUseQueryThreadId =
|
||||
pathname.startsWith("/workspace/chats/") &&
|
||||
!!queryThreadIdFromParams &&
|
||||
(xClawUsedFromQuery === "true" || isNewFromQuery);
|
||||
const effectiveThreadIdFromPath =
|
||||
normalizeThreadId(threadIdFromPath) ?? readStoredThreadId();
|
||||
console.log("[useThreadChat] effectiveThreadIdFromPath", effectiveThreadIdFromPath);
|
||||
|
||||
const [threadId, setThreadId] = useState(() => {
|
||||
if (threadIdFromPath === "new") {
|
||||
return shouldUseQueryThreadId ? queryThreadIdFromParams : undefined;
|
||||
}
|
||||
return threadIdFromPath;
|
||||
return effectiveThreadIdFromPath ?? undefined;
|
||||
});
|
||||
|
||||
const [isNewThread, setIsNewThread] = useState(
|
||||
|
|
@ -29,25 +69,22 @@ export function useThreadChat() {
|
|||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (threadId && threadId !== "new" && typeof window !== "undefined") {
|
||||
window.sessionStorage.setItem("workspace.thread_id", threadId);
|
||||
}
|
||||
if (pathname.endsWith("/new")) {
|
||||
setIsNewThread(true);
|
||||
const nextQueryThreadId = searchParams.get("thread_id")?.trim();
|
||||
const nextQueryThreadId = readQueryThreadId();
|
||||
const nextIsNewFromQuery =
|
||||
searchParams.get("isnew")?.trim().toLowerCase() === "false";
|
||||
const nextXClawUsed = searchParams.get("xclaw_used");
|
||||
const nextShouldUseQueryThreadId =
|
||||
pathname.startsWith("/workspace/chats/") &&
|
||||
!!nextQueryThreadId &&
|
||||
(nextXClawUsed === "true" || nextIsNewFromQuery);
|
||||
if (nextShouldUseQueryThreadId && nextQueryThreadId) {
|
||||
router.replace(`/workspace/chats/${nextQueryThreadId}`);
|
||||
return;
|
||||
}
|
||||
setThreadId(nextShouldUseQueryThreadId ? nextQueryThreadId : undefined);
|
||||
setThreadId(nextQueryThreadId ?? undefined);
|
||||
return;
|
||||
}
|
||||
setIsNewThread(false);
|
||||
setThreadId(threadIdFromPath);
|
||||
console.log("threadIdFromPath", threadIdFromPath, "normalized", normalizeThreadId(threadIdFromPath));
|
||||
|
||||
setThreadId(normalizeThreadId(threadIdFromPath));
|
||||
}, [pathname, router, searchParams, threadIdFromPath]);
|
||||
const isMock = searchParams.get("mock") === "true";
|
||||
return { threadId, isNewThread, setIsNewThread, isMock };
|
||||
|
|
|
|||
Loading…
Reference in New Issue