fix: prevent TaskLane showing stale data when starting new chat
Three race conditions in AssistantChatPage: 1. handleNewChat cleared showTaskLane/activeQuestions/activeActions AFTER the createChatSession await — old lane was visible during the network call. Moved clears before the await. 2. handleResumeNew never cleared old TaskLane state at all. Added upfront clears before the first await. 3. handleSend and handleTaskSubmit had no stale-session guard. If the user switched chats while sendChatMessage was in flight, the response would set showTaskLane on the wrong session. Added sentForChatId snapshot + currentChatRef guard (same pattern already used in selectChat). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -259,6 +259,11 @@ export default function AssistantChatPage() {
|
||||
}, [])
|
||||
|
||||
const handleNewChat = async () => {
|
||||
// Clear stale state immediately — don't wait for API to return
|
||||
setShowTaskLane(false)
|
||||
setActiveQuestions([])
|
||||
setActiveActions([])
|
||||
setMessages([])
|
||||
try {
|
||||
const session = await aiSessionsApi.createChatSession({
|
||||
intake_type: 'free_text',
|
||||
@@ -275,11 +280,6 @@ export default function AssistantChatPage() {
|
||||
currentChatRef.current = session.session_id
|
||||
setChats(prev => [chatItem, ...prev])
|
||||
setActiveChatId(session.session_id)
|
||||
setMessages([])
|
||||
// Clear TaskLane from previous session
|
||||
setShowTaskLane(false)
|
||||
setActiveQuestions([])
|
||||
setActiveActions([])
|
||||
} catch {
|
||||
toast.error('Failed to create chat')
|
||||
}
|
||||
@@ -315,11 +315,14 @@ export default function AssistantChatPage() {
|
||||
setMessages(prev => [...prev, { role: 'user', content: userMessage }])
|
||||
setLoading(true)
|
||||
|
||||
const sentForChatId = activeChatId
|
||||
try {
|
||||
const response = await aiSessionsApi.sendChatMessage(activeChatId, {
|
||||
message: userMessage,
|
||||
upload_ids: completedUploadIds.length > 0 ? completedUploadIds : undefined,
|
||||
})
|
||||
// Guard: discard if user switched to a different chat while this was in flight
|
||||
if (currentChatRef.current !== sentForChatId) return
|
||||
analytics.aiFeatureUsed({ feature: 'assistant_chat' })
|
||||
setMessages(prev => [
|
||||
...prev,
|
||||
@@ -327,20 +330,20 @@ export default function AssistantChatPage() {
|
||||
])
|
||||
setChats(prev =>
|
||||
prev.map(c =>
|
||||
c.id === activeChatId
|
||||
c.id === sentForChatId
|
||||
? { ...c, message_count: c.message_count + 2, title: c.message_count === 0 ? userMessage.slice(0, 100) : c.title, updated_at: new Date().toISOString() }
|
||||
: c
|
||||
)
|
||||
)
|
||||
// Load branches if fork was created
|
||||
if (response.fork && activeChatId) {
|
||||
branching.loadBranches(activeChatId)
|
||||
if (response.fork && sentForChatId) {
|
||||
branching.loadBranches(sentForChatId)
|
||||
}
|
||||
// Show task lane if AI sent questions or actions
|
||||
const hasQuestions = response.questions && response.questions.length > 0
|
||||
const hasActions = response.actions && response.actions.length > 0
|
||||
if (hasQuestions || hasActions) {
|
||||
if (activeChatId) clearTaskState(activeChatId)
|
||||
clearTaskState(sentForChatId)
|
||||
setActiveQuestions(response.questions || [])
|
||||
setActiveActions(response.actions || [])
|
||||
setShowTaskLane(true)
|
||||
@@ -377,19 +380,22 @@ export default function AssistantChatPage() {
|
||||
setMessages(prev => [...prev, { role: 'user', content: userMessage }])
|
||||
setLoading(true)
|
||||
|
||||
const sentForChatId = activeChatId
|
||||
try {
|
||||
const response = await aiSessionsApi.sendChatMessage(activeChatId, { message: userMessage })
|
||||
// Guard: discard if user switched to a different chat while this was in flight
|
||||
if (currentChatRef.current !== sentForChatId) return
|
||||
setMessages(prev => [
|
||||
...prev,
|
||||
{ role: 'assistant', content: response.content, suggestedFlows: response.suggested_flows, fork: response.fork, actions: response.actions, questions: response.questions },
|
||||
])
|
||||
if (response.fork && activeChatId) {
|
||||
branching.loadBranches(activeChatId)
|
||||
if (response.fork && sentForChatId) {
|
||||
branching.loadBranches(sentForChatId)
|
||||
}
|
||||
// Update task lane based on AI response
|
||||
const hasQuestions = response.questions && response.questions.length > 0
|
||||
const hasActions = response.actions && response.actions.length > 0
|
||||
if (activeChatId) clearTaskState(activeChatId)
|
||||
clearTaskState(sentForChatId)
|
||||
if (hasQuestions || hasActions) {
|
||||
setActiveQuestions(response.questions || [])
|
||||
setActiveActions(response.actions || [])
|
||||
@@ -430,6 +436,10 @@ export default function AssistantChatPage() {
|
||||
}
|
||||
|
||||
const handleResumeNew = async (summary: string) => {
|
||||
// Clear stale state immediately — don't wait for API to return
|
||||
setShowTaskLane(false)
|
||||
setActiveQuestions([])
|
||||
setActiveActions([])
|
||||
try {
|
||||
const resumePrompt = `I'm continuing a previous troubleshooting session. Here's where we left off:\n\n${summary}\n\nPlease review this context and help me continue from where we stopped.`
|
||||
const session = await aiSessionsApi.createChatSession({
|
||||
|
||||
Reference in New Issue
Block a user