fix(workspace): 恢复先删后建并修复新会话初始化时序
- 新会话初始化改为 delete -> create - 通过初始化就绪门控,确保 history 在创建完成后再加载 - 发送消息前等待初始化完成,避免与初始化并发
This commit is contained in:
parent
d1cdb7eef7
commit
08e8de5e3e
|
|
@ -81,16 +81,23 @@ export default function ChatPage() {
|
||||||
() => isNewThread && !safeThreadId,
|
() => isNewThread && !safeThreadId,
|
||||||
[isNewThread, safeThreadId],
|
[isNewThread, safeThreadId],
|
||||||
);
|
);
|
||||||
|
const [isThreadInitReady, setIsThreadInitReady] = useState(false);
|
||||||
|
|
||||||
const streamThreadId = useMemo(() => {
|
const streamThreadId = useMemo(() => {
|
||||||
if (isNewThread && createNewSession) {
|
if (!safeThreadId) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
// In /new flow, defer history loading until thread init is finished:
|
||||||
|
// delete -> create -> history.
|
||||||
|
if (isNewThread && !isThreadInitReady) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
return safeThreadId;
|
return safeThreadId;
|
||||||
}, [createNewSession, isNewThread, safeThreadId]);
|
}, [isNewThread, isThreadInitReady, safeThreadId]);
|
||||||
const apiClient = useMemo(() => getAPIClient(isMock), [isMock]);
|
const apiClient = useMemo(() => getAPIClient(isMock), [isMock]);
|
||||||
const warnedMissingThreadIdRef = useRef(false);
|
const warnedMissingThreadIdRef = useRef(false);
|
||||||
const initializedThreadRef = useRef<string | null>(null);
|
const initializedThreadRef = useRef<string | null>(null);
|
||||||
|
const threadInitPromiseRef = useRef<Promise<void> | null>(null);
|
||||||
|
|
||||||
const { showNotification } = useNotification();
|
const { showNotification } = useNotification();
|
||||||
const currentSlogan = motivationSlogans[
|
const currentSlogan = motivationSlogans[
|
||||||
|
|
@ -130,6 +137,7 @@ export default function ChatPage() {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isNewThread) {
|
if (!isNewThread) {
|
||||||
warnedMissingThreadIdRef.current = false;
|
warnedMissingThreadIdRef.current = false;
|
||||||
|
setIsThreadInitReady(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!safeThreadId) {
|
if (!safeThreadId) {
|
||||||
|
|
@ -137,29 +145,38 @@ export default function ChatPage() {
|
||||||
warnedMissingThreadIdRef.current = true;
|
warnedMissingThreadIdRef.current = true;
|
||||||
toast.error(t.chatPage.missingThreadIdForCreate);
|
toast.error(t.chatPage.missingThreadIdForCreate);
|
||||||
}
|
}
|
||||||
|
setIsThreadInitReady(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
warnedMissingThreadIdRef.current = false;
|
warnedMissingThreadIdRef.current = false;
|
||||||
if (initializedThreadRef.current === safeThreadId) return;
|
if (initializedThreadRef.current === safeThreadId) return;
|
||||||
initializedThreadRef.current = safeThreadId;
|
initializedThreadRef.current = safeThreadId;
|
||||||
void apiClient.threads
|
setIsThreadInitReady(false);
|
||||||
// TODO: 先注释先删除再创建的逻辑
|
|
||||||
// .delete(safeThreadId)
|
const initPromise = apiClient.threads
|
||||||
// .catch(() => undefined)
|
.delete(safeThreadId)
|
||||||
// .then(() =>
|
.catch(() => undefined)
|
||||||
// apiClient.threads.create({
|
.then(() =>
|
||||||
// threadId: safeThreadId,
|
apiClient.threads.create({
|
||||||
// ifExists: "raise",
|
|
||||||
// }),
|
|
||||||
// )
|
|
||||||
.create({
|
|
||||||
threadId: safeThreadId,
|
threadId: safeThreadId,
|
||||||
ifExists: "do_nothing",
|
ifExists: "do_nothing",
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.then(() => {
|
||||||
|
setIsThreadInitReady(true);
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
initializedThreadRef.current = null;
|
initializedThreadRef.current = null;
|
||||||
|
setIsThreadInitReady(false);
|
||||||
toast.error(t.chatPage.createSessionFailed);
|
toast.error(t.chatPage.createSessionFailed);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
threadInitPromiseRef.current = initPromise;
|
||||||
|
void initPromise.finally(() => {
|
||||||
|
if (threadInitPromiseRef.current === initPromise) {
|
||||||
|
threadInitPromiseRef.current = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
}, [
|
}, [
|
||||||
apiClient,
|
apiClient,
|
||||||
isNewThread,
|
isNewThread,
|
||||||
|
|
@ -291,7 +308,7 @@ export default function ChatPage() {
|
||||||
const [showExitDialog, setShowExitDialog] = useState(false);
|
const [showExitDialog, setShowExitDialog] = useState(false);
|
||||||
const isStreaming = isUploading || thread.isLoading;
|
const isStreaming = isUploading || thread.isLoading;
|
||||||
const handleSubmit = useCallback(
|
const handleSubmit = useCallback(
|
||||||
(message: Parameters<typeof sendMessage>[1]) => {
|
async (message: Parameters<typeof sendMessage>[1]) => {
|
||||||
if (isSelectedSkillBootstrapping) {
|
if (isSelectedSkillBootstrapping) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -299,6 +316,12 @@ export default function ChatPage() {
|
||||||
toast.error(t.chatPage.missingThreadIdForSend);
|
toast.error(t.chatPage.missingThreadIdForSend);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (isNewThread && safeThreadId) {
|
||||||
|
await threadInitPromiseRef.current;
|
||||||
|
}
|
||||||
|
if (isNewThread && safeThreadId && !isThreadInitReady) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
setHasSubmitted(true);
|
setHasSubmitted(true);
|
||||||
if (safeThreadId && (isNewThread || showWelcomeStyle)) {
|
if (safeThreadId && (isNewThread || showWelcomeStyle)) {
|
||||||
router.replace(`/workspace/chats/${safeThreadId}?is_chatting=true`);
|
router.replace(`/workspace/chats/${safeThreadId}?is_chatting=true`);
|
||||||
|
|
@ -307,6 +330,7 @@ export default function ChatPage() {
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
isNewThread,
|
isNewThread,
|
||||||
|
isThreadInitReady,
|
||||||
isSelectedSkillBootstrapping,
|
isSelectedSkillBootstrapping,
|
||||||
router,
|
router,
|
||||||
safeThreadId,
|
safeThreadId,
|
||||||
|
|
@ -633,14 +657,14 @@ export default function ChatPage() {
|
||||||
type: POST_MESSAGE_TYPES.IS_CHATTING,
|
type: POST_MESSAGE_TYPES.IS_CHATTING,
|
||||||
isChatting: false,
|
isChatting: false,
|
||||||
});
|
});
|
||||||
resetNewSessionState();
|
|
||||||
// 始终复用 query 中的 thread_id。
|
// 始终复用 query 中的 thread_id。
|
||||||
const nextQuery = new URLSearchParams();
|
const nextQuery = new URLSearchParams();
|
||||||
if (threadId && threadId !== "new") {
|
if (threadId && threadId !== "new") {
|
||||||
nextQuery.set("thread_id", threadId);
|
nextQuery.set("thread_id", threadId);
|
||||||
}
|
}
|
||||||
|
// /workspace/chats/${threadId}?is_chatting=false
|
||||||
router.replace(
|
router.replace(
|
||||||
`/workspace/chats/${threadId}?is_chatting=false`,
|
`/workspace/chats/new?thread_id=${threadId}`,
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue