diff --git a/backend/app/api/endpoints/ai_sessions.py b/backend/app/api/endpoints/ai_sessions.py index 4ffd7097..537737e6 100644 --- a/backend/app/api/endpoints/ai_sessions.py +++ b/backend/app/api/endpoints/ai_sessions.py @@ -117,6 +117,9 @@ def _build_session_detail(session: AISession) -> AISessionDetail: resolved_at=session.resolved_at, steps=step_responses, conversation_messages=session.conversation_messages or [], + pending_task_lane=session.pending_task_lane, + is_branching=getattr(session, 'is_branching', False), + active_branch_id=str(session.active_branch_id) if getattr(session, 'active_branch_id', None) else None, ) diff --git a/frontend/src/components/script-editor/ScriptTemplateEditor.tsx b/frontend/src/components/script-editor/ScriptTemplateEditor.tsx index 0b3a8671..d0e3228e 100644 --- a/frontend/src/components/script-editor/ScriptTemplateEditor.tsx +++ b/frontend/src/components/script-editor/ScriptTemplateEditor.tsx @@ -1,4 +1,4 @@ -import { useState, useEffect } from 'react' +import { useState, useEffect, useRef } from 'react' import { ArrowLeft, Loader2, Save, Scan, Trash2 } from 'lucide-react' import { Input } from '@/components/ui/Input' import { Textarea } from '@/components/ui/Textarea' @@ -64,16 +64,19 @@ export function ScriptTemplateEditor({ templateId, onBack, onSaved }: Props) { const [detectedCandidates, setDetectedCandidates] = useState([]) const [showStepper, setShowStepper] = useState(false) const [detectionSummary, setDetectionSummary] = useState(null) + const acceptingCandidateRef = useRef(false) const { canShareScriptTemplate } = usePermissions() - // Dismiss stepper if user edits the script body during detection + // Dismiss stepper if user manually edits the script body during detection + // (but NOT when handleAcceptCandidate programmatically updates script_body) const scriptBodyRef = form.script_body useEffect(() => { - if (showStepper) { + if (showStepper && !acceptingCandidateRef.current) { setShowStepper(false) setDetectedCandidates([]) } + acceptingCandidateRef.current = false // eslint-disable-next-line react-hooks/exhaustive-deps }, [scriptBodyRef]) @@ -263,6 +266,7 @@ export function ScriptTemplateEditor({ templateId, onBack, onSaved }: Props) { sensitive: overrides.sensitive, } + acceptingCandidateRef.current = true setForm(f => ({ ...f, script_body: updatedScript, diff --git a/frontend/src/pages/AssistantChatPage.tsx b/frontend/src/pages/AssistantChatPage.tsx index 3a95f680..30e20a2b 100644 --- a/frontend/src/pages/AssistantChatPage.tsx +++ b/frontend/src/pages/AssistantChatPage.tsx @@ -102,7 +102,9 @@ export default function AssistantChatPage() { // Restore session from sessionStorage on mount (when URL has no session ID) useEffect(() => { + console.log('[AssistantChat] Mount restore check — urlSessionId:', urlSessionId, 'activeChatId:', activeChatId) if (!urlSessionId && activeChatId) { + console.log('[AssistantChat] Calling selectChat to restore:', activeChatId) selectChat(activeChatId) } }, []) // eslint-disable-line react-hooks/exhaustive-deps @@ -207,6 +209,7 @@ export default function AssistantChatPage() { } const selectChat = useCallback(async (chatId: string) => { + console.log('[AssistantChat] selectChat called with:', chatId) setActiveChatId(chatId) // Clear TaskLane when switching chats — will restore from backend if available setShowTaskLane(false) @@ -214,6 +217,7 @@ export default function AssistantChatPage() { setActiveActions([]) try { const detail = await aiSessionsApi.getSession(chatId) + console.log('[AssistantChat] getSession response — messages:', detail.conversation_messages?.length, 'pending_task_lane:', !!detail.pending_task_lane) setMessages( (detail.conversation_messages || []).map(m => ({ role: m.role as 'user' | 'assistant', @@ -237,7 +241,8 @@ export default function AssistantChatPage() { } } } - } catch { + } catch (err) { + console.error('[AssistantChat] Failed to load chat session:', err) setMessages([]) } }, [])