fix(ai): clear conversation actually clears

useChat exposes reset() which calls setMessages(opts.initialMessages),
and the AI page passes initialLive.current as initialMessages — a ref
captured once on mount from localStorage.

resetAndClear was calling reset() then clearLive(). Sequence problem:

  reset()       → setMessages(initialLive.current)  // populated old array
  clearLive()   → localStorage.removeItem(LIVE_KEY) // does nothing to memory

The ref still held the original messages, so reset re-seeded them and
the conversation appeared to "come back" the moment you typed anything
(or sometimes immediately, depending on render timing).

Fix: blank the ref, clear localStorage, and call setMessages([])
directly. reset() is no longer needed at this call site so it's been
dropped from the useChat destructure.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
jules
2026-05-02 19:59:32 +10:00
parent 2a68389121
commit a770faf6eb

View File

@@ -378,7 +378,7 @@ function ChatSurface({
if (initialLive.current === null) { if (initialLive.current === null) {
initialLive.current = loadLive() ?? [] initialLive.current = loadLive() ?? []
} }
const { messages, setMessages, send, continueChat, abort, isStreaming, reset } = useChat({ const { messages, setMessages, send, continueChat, abort, isStreaming } = useChat({
system: systemPrompt, system: systemPrompt,
initialMessages: initialLive.current, initialMessages: initialLive.current,
}) })
@@ -389,11 +389,20 @@ function ChatSurface({
saveLive(messages) saveLive(messages)
}, [messages]) }, [messages])
// Wrap reset so "Clear conversation" also drops the persisted snapshot. // "Clear conversation" must drop three things in lockstep:
// 1. The in-memory messages (setMessages([])).
// 2. The persisted live snapshot (clearLive()).
// 3. The initialLive ref — otherwise on the next render or hook
// reconciliation, useChat's reset() would re-seed from the
// captured-at-mount initialMessages and the old conversation
// pops back. (This was the bug.)
// We deliberately don't call useChat's reset() here because reset
// restores to opts.initialMessages, which we want to be empty.
const resetAndClear = useCallback(() => { const resetAndClear = useCallback(() => {
reset() initialLive.current = []
clearLive() clearLive()
}, [reset]) setMessages([])
}, [setMessages])
// Auto tool-loop using native function calls. Reads run automatically; // Auto tool-loop using native function calls. Reads run automatically;
// writes are held in `pendingConfirm` until the operator clicks Confirm // writes are held in `pendingConfirm` until the operator clicks Confirm