Pulastya B commited on
Commit
554eeb5
Β·
1 Parent(s): e29cf28

Fixed Chat Session issues

Browse files
FRRONTEEEND/GDG on Campus - DevSprint Slides Template.pdf DELETED
The diff for this file is too large to render. See raw diff
 
FRRONTEEEND/components/ChatInterface.tsx CHANGED
@@ -33,16 +33,20 @@ interface ChatSession {
33
  updatedAt: Date;
34
  }
35
 
 
 
 
 
 
 
36
  export const ChatInterface: React.FC<{ onBack: () => void }> = ({ onBack }) => {
37
- const [sessions, setSessions] = useState<ChatSession[]>([
38
- {
39
- id: '1',
40
- title: 'ML Model Analysis',
41
- messages: [],
42
- updatedAt: new Date(),
43
- }
44
- ]);
45
- const [activeSessionId, setActiveSessionId] = useState<string>('1'); // Start with default session, update to UUID after first API call
46
  const [input, setInput] = useState('');
47
  const [isTyping, setIsTyping] = useState(false);
48
  const [currentStep, setCurrentStep] = useState<string>('');
@@ -63,41 +67,55 @@ export const ChatInterface: React.FC<{ onBack: () => void }> = ({ onBack }) => {
63
  }
64
  }, [activeSession.messages, isTyping]);
65
 
66
- // Clear uploaded file when switching sessions
67
  useEffect(() => {
68
  setUploadedFile(null);
69
  if (fileInputRef.current) {
70
  fileInputRef.current.value = '';
71
  }
 
 
 
72
  }, [activeSessionId]);
73
 
 
 
 
74
  // Connect to SSE when we receive a valid backend UUID
75
  useEffect(() => {
76
- // Only connect if we have a backend UUID (contains hyphens)
77
- if (!activeSessionId || !activeSessionId.includes('-')) {
 
 
 
 
 
 
 
 
 
78
  return;
79
  }
80
 
81
- // Check if we need a new connection for this session
82
- // Close old connection if it exists and belongs to a different session or is closed
83
- if (eventSourceRef.current) {
84
- const currentSource = eventSourceRef.current;
85
- // If readyState is CLOSED (2), we need a new connection
86
- // If it's CONNECTING (0) or OPEN (1) for the same session, reuse it
87
- if (currentSource.readyState === 2) {
88
- console.log('πŸ”„ Existing connection closed, creating new one');
89
- currentSource.close();
90
  eventSourceRef.current = null;
91
- } else {
92
- console.log('♻️ Reusing existing SSE connection');
93
- return;
94
  }
 
 
 
 
95
  }
96
 
97
- // Connect to SSE stream - will receive history + any new events
98
  const API_URL = window.location.origin;
99
- console.log(`πŸ”Œ Connecting SSE to session: ${activeSessionId}`);
100
  const eventSource = new EventSource(`${API_URL}/api/progress/stream/${activeSessionId}`);
 
101
 
102
  eventSource.onopen = () => {
103
  console.log('βœ… SSE connection established');
@@ -169,6 +187,7 @@ export const ChatInterface: React.FC<{ onBack: () => void }> = ({ onBack }) => {
169
  console.log('🧹 Cleaning up SSE connection');
170
  eventSourceRef.current.close();
171
  eventSourceRef.current = null;
 
172
  }
173
  };
174
  }, [activeSessionId]);
@@ -287,31 +306,30 @@ export const ChatInterface: React.FC<{ onBack: () => void }> = ({ onBack }) => {
287
  let response;
288
  const sessionKey = activeSessionId || 'default';
289
 
 
 
 
290
  // Check if there's a recent file analysis in the conversation
291
- const recentFileMessage = newMessages.slice(-5).find(m => m.file || m.content.includes('Uploaded:'));
292
- const hasRecentFile = recentFileMessage && !uploadedFile;
293
 
294
- if (uploadedFile || hasRecentFile) {
295
- // Use /run endpoint for file analysis or follow-up questions about uploaded data
 
 
 
296
  const formData = new FormData();
297
 
298
  if (uploadedFile) {
299
  formData.append('file', uploadedFile);
300
  formData.append('task_description', input || 'Analyze this dataset and provide insights');
301
- formData.append('session_id', sessionKey); // Add session_id for progress tracking
302
- } else if (hasRecentFile) {
303
- // For follow-up questions, extract the filename from recent context
304
- const fileNameMatch = recentFileMessage?.content.match(/Uploaded: (.+)/);
305
- const fileName = fileNameMatch ? fileNameMatch[1] : 'dataset.csv';
306
-
307
- // Send follow-up request as a new task description
308
  formData.append('task_description', input);
309
- formData.append('session_id', sessionKey); // Use same session key
310
-
311
- // Note: Backend needs to support session-based file context
312
- // For now, just send the task which should work with session memory
313
  }
314
 
 
315
  formData.append('use_cache', 'false'); // Disabled to show multi-agent execution
316
  formData.append('max_iterations', '20');
317
 
@@ -322,6 +340,7 @@ export const ChatInterface: React.FC<{ onBack: () => void }> = ({ onBack }) => {
322
 
323
  setUploadedFile(null);
324
  } else {
 
325
  response = await fetch(`${API_URL}/chat`, {
326
  method: 'POST',
327
  headers: {
@@ -519,7 +538,9 @@ export const ChatInterface: React.FC<{ onBack: () => void }> = ({ onBack }) => {
519
  };
520
 
521
  const createNewChat = () => {
522
- const newId = Date.now().toString();
 
 
523
  const newSession: ChatSession = {
524
  id: newId,
525
  title: 'New Chat',
@@ -534,6 +555,12 @@ export const ChatInterface: React.FC<{ onBack: () => void }> = ({ onBack }) => {
534
  if (fileInputRef.current) {
535
  fileInputRef.current.value = '';
536
  }
 
 
 
 
 
 
537
  };
538
 
539
  const deleteSession = (e: React.MouseEvent, id: string) => {
 
33
  updatedAt: Date;
34
  }
35
 
36
+ // Generate a unique local session ID (not a backend UUID)
37
+ const generateLocalSessionId = () => `local_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
38
+
39
+ // Initial session ID - generated once when module loads
40
+ const INITIAL_SESSION_ID = generateLocalSessionId();
41
+
42
  export const ChatInterface: React.FC<{ onBack: () => void }> = ({ onBack }) => {
43
+ const [sessions, setSessions] = useState<ChatSession[]>([{
44
+ id: INITIAL_SESSION_ID,
45
+ title: 'New Chat',
46
+ messages: [],
47
+ updatedAt: new Date(),
48
+ }]);
49
+ const [activeSessionId, setActiveSessionId] = useState<string>(INITIAL_SESSION_ID);
 
 
50
  const [input, setInput] = useState('');
51
  const [isTyping, setIsTyping] = useState(false);
52
  const [currentStep, setCurrentStep] = useState<string>('');
 
67
  }
68
  }, [activeSession.messages, isTyping]);
69
 
70
+ // Clear state when switching sessions
71
  useEffect(() => {
72
  setUploadedFile(null);
73
  if (fileInputRef.current) {
74
  fileInputRef.current.value = '';
75
  }
76
+ // Clear processed results tracker for new session
77
+ // (keeps results from old session from blocking new ones)
78
+ processedAnalysisRef.current.clear();
79
  }, [activeSessionId]);
80
 
81
+ // Track which session the current SSE connection is for
82
+ const sseSessionRef = useRef<string | null>(null);
83
+
84
  // Connect to SSE when we receive a valid backend UUID
85
  useEffect(() => {
86
+ // Only connect if we have a backend UUID (contains hyphens, not a local_ ID)
87
+ const isBackendUUID = activeSessionId && activeSessionId.includes('-') && !activeSessionId.startsWith('local_');
88
+
89
+ if (!isBackendUUID) {
90
+ // No backend session yet - close any existing connection
91
+ if (eventSourceRef.current) {
92
+ console.log('πŸ”Œ Closing SSE - no backend session');
93
+ eventSourceRef.current.close();
94
+ eventSourceRef.current = null;
95
+ sseSessionRef.current = null;
96
+ }
97
  return;
98
  }
99
 
100
+ // Check if we're switching to a DIFFERENT session
101
+ if (sseSessionRef.current !== activeSessionId) {
102
+ // Close old connection if it exists (switching sessions)
103
+ if (eventSourceRef.current) {
104
+ console.log(`πŸ”„ Switching SSE from ${sseSessionRef.current?.slice(0, 8)}... to ${activeSessionId.slice(0, 8)}...`);
105
+ eventSourceRef.current.close();
 
 
 
106
  eventSourceRef.current = null;
 
 
 
107
  }
108
+ } else if (eventSourceRef.current && eventSourceRef.current.readyState !== 2) {
109
+ // Same session and connection is still open - reuse it
110
+ console.log('♻️ Reusing existing SSE connection');
111
+ return;
112
  }
113
 
114
+ // Connect to SSE stream for this session
115
  const API_URL = window.location.origin;
116
+ console.log(`πŸ”Œ Connecting SSE to session: ${activeSessionId.slice(0, 8)}...`);
117
  const eventSource = new EventSource(`${API_URL}/api/progress/stream/${activeSessionId}`);
118
+ sseSessionRef.current = activeSessionId;
119
 
120
  eventSource.onopen = () => {
121
  console.log('βœ… SSE connection established');
 
187
  console.log('🧹 Cleaning up SSE connection');
188
  eventSourceRef.current.close();
189
  eventSourceRef.current = null;
190
+ sseSessionRef.current = null;
191
  }
192
  };
193
  }, [activeSessionId]);
 
306
  let response;
307
  const sessionKey = activeSessionId || 'default';
308
 
309
+ // Detect if we have an active backend session (UUID format)
310
+ const hasBackendSession = sessionKey.includes('-') && sessionKey.length > 20;
311
+
312
  // Check if there's a recent file analysis in the conversation
313
+ const recentFileMessage = newMessages.find(m => m.file || m.content.includes('Uploaded:'));
314
+ const isFileAnalysis = uploadedFile || recentFileMessage;
315
 
316
+ // πŸ”‘ KEY CHANGE: Always use /run-async if:
317
+ // 1. User is uploading a file, OR
318
+ // 2. We have an active backend session (meaning we've done file analysis before)
319
+ if (uploadedFile || hasBackendSession) {
320
+ // Use /run-async endpoint for file analysis or follow-up questions
321
  const formData = new FormData();
322
 
323
  if (uploadedFile) {
324
  formData.append('file', uploadedFile);
325
  formData.append('task_description', input || 'Analyze this dataset and provide insights');
326
+ } else {
327
+ // Follow-up query - send task description only, backend will use cached dataset
 
 
 
 
 
328
  formData.append('task_description', input);
329
+ console.log(`πŸ“€ Follow-up query for session ${sessionKey.slice(0, 8)}...`);
 
 
 
330
  }
331
 
332
+ formData.append('session_id', sessionKey);
333
  formData.append('use_cache', 'false'); // Disabled to show multi-agent execution
334
  formData.append('max_iterations', '20');
335
 
 
340
 
341
  setUploadedFile(null);
342
  } else {
343
+ // No file and no backend session - use simple chat endpoint
344
  response = await fetch(`${API_URL}/chat`, {
345
  method: 'POST',
346
  headers: {
 
538
  };
539
 
540
  const createNewChat = () => {
541
+ // Generate a unique local ID for this chat session
542
+ // The backend will generate the real UUID when the first request is made
543
+ const newId = generateLocalSessionId();
544
  const newSession: ChatSession = {
545
  id: newId,
546
  title: 'New Chat',
 
555
  if (fileInputRef.current) {
556
  fileInputRef.current.value = '';
557
  }
558
+
559
+ // Close any existing SSE connection since this is a fresh chat
560
+ if (eventSourceRef.current) {
561
+ eventSourceRef.current.close();
562
+ eventSourceRef.current = null;
563
+ }
564
  };
565
 
566
  const deleteSession = (e: React.MouseEvent, id: string) => {