fix(ai-chat): keep the live thread on new-chat adoption; log stream errors
A brand-new chat's first turn streamed and finished successfully, but the whole assistant response vanished from the UI. On finish the window adopts the server-created chat id, which changed the <ChatThread> key and remounted it — discarding the live useChat store (the full answer) and re-seeding from not-yet-persisted history, so only the user message remained. - chat-thread: pin the useChat store id to a per-mount value so adopting the chatId prop no longer recreates the store and wipes the live turn. - ai-chat-window: derive the thread mount key via setState-during-render and move the live-thread marker in lockstep with the adopted id, so in-place adoption keeps the same mounted thread while real chat switches still remount and re-seed; gate the history loader to a freshly opened chat. - cancel a pending adoption on New chat / explicit chat selection. - log the raw stream error to the browser console for debugging. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -129,7 +129,13 @@ export default function ChatThread({
|
||||
// The id only needs to be stable per mount — the parent remounts this via
|
||||
// `key` on chat switch, which re-seeds cleanly.
|
||||
const stableIdRef = useRef<string>(chatId ?? `new-${generateId()}`);
|
||||
const chatStoreId = chatId ?? stableIdRef.current;
|
||||
// Stable for the LIFETIME of this mount. When a brand-new chat adopts its
|
||||
// server id, the parent now updates the `chatId` prop WITHOUT remounting this
|
||||
// thread, so the store id must NOT follow `chatId`: recreating the useChat
|
||||
// store would wipe the live (just-finished) turn. The server still resolves
|
||||
// the real chat from `chatId` in the request body (see chatIdRef /
|
||||
// prepareSendMessagesRequest), so this purely-client store key can stay fixed.
|
||||
const chatStoreId = stableIdRef.current;
|
||||
|
||||
const transport = useMemo(
|
||||
() =>
|
||||
@@ -170,7 +176,12 @@ export default function ChatThread({
|
||||
// saves the error message). Run the same post-turn path on error so the
|
||||
// failed chat appears in history immediately instead of after a manual
|
||||
// refresh. The error itself is still surfaced via `error` below.
|
||||
onError: () => onTurnFinished(),
|
||||
onError: (streamError) => {
|
||||
// Surface the raw failure in the browser console (devtools) for debugging;
|
||||
// the UI separately shows a friendly classified banner (see errorView).
|
||||
console.error("AI chat stream error:", streamError);
|
||||
onTurnFinished();
|
||||
},
|
||||
});
|
||||
|
||||
const isStreaming = status === "submitted" || status === "streaming";
|
||||
|
||||
Reference in New Issue
Block a user