fix:fixed and finished chatbot integration
This commit is contained in:
parent
23508eaa74
commit
836b8032ae
3 changed files with 90 additions and 71 deletions
|
|
@ -181,11 +181,7 @@ export function FormGeneratorControls({
|
|||
size="sm"
|
||||
icon={FaTrash}
|
||||
>
|
||||
<<<<<<< HEAD
|
||||
{allItemsSelected
|
||||
=======
|
||||
{selectedCount === displayData.length && displayData.length > 0
|
||||
>>>>>>> c76e7efd28210f45737b5afbdddff2712b2c0cc7
|
||||
? t('formgen.delete.all', `Delete all ${selectedCount} items`).replace('{count}', selectedCount.toString())
|
||||
: t('formgen.delete.multiple', `Delete ${selectedCount} selected items`).replace('{count}', selectedCount.toString())}
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -1006,7 +1006,12 @@ const PageRenderer: React.FC<PageRendererProps> = ({
|
|||
const buttonVariant = isRunning
|
||||
? (config.stopButtonVariant || config.buttonVariant || 'primary')
|
||||
: (config.buttonVariant || 'primary');
|
||||
const buttonDisabled = hookData.isSubmitting || (!isRunning && !hookData.inputValue?.trim());
|
||||
// Button disabled logic:
|
||||
// - Always enabled when running (to allow stopping), unless submitting
|
||||
// - When not running, disabled if submitting or input is empty
|
||||
const buttonDisabled = isRunning
|
||||
? hookData.isSubmitting // When running, only disable if submitting
|
||||
: (hookData.isSubmitting || !hookData.inputValue?.trim()); // When not running, disable if submitting or input empty
|
||||
|
||||
// Handle Enter key press
|
||||
const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ export function useChatbot() {
|
|||
const thinkingLogsRef = useRef<string[]>([]); // Use ref instead of state to avoid batching
|
||||
const logQueueRef = useRef<string[]>([]); // Queue for logs to process one by one
|
||||
const isProcessingLogsRef = useRef<boolean>(false); // Flag to prevent concurrent processing
|
||||
const processedLogsRef = useRef<Set<string>>(new Set()); // Track processed logs to prevent duplicates
|
||||
|
||||
// Clear processed message IDs when workflow changes
|
||||
const clearProcessedMessages = useCallback(() => {
|
||||
|
|
@ -65,16 +66,18 @@ export function useChatbot() {
|
|||
// Clear log queue and stop processing
|
||||
logQueueRef.current = [];
|
||||
isProcessingLogsRef.current = false;
|
||||
processedLogsRef.current.clear(); // Clear processed logs tracking
|
||||
|
||||
if (thinkingMessageIdRef.current) {
|
||||
const thinkingId = thinkingMessageIdRef.current;
|
||||
thinkingMessageIdRef.current = null;
|
||||
thinkingLogsRef.current = [];
|
||||
|
||||
setMessages(prevMessages => {
|
||||
return prevMessages.filter(m => m.id !== thinkingId);
|
||||
});
|
||||
}
|
||||
// Reset thinking message refs
|
||||
const thinkingId = thinkingMessageIdRef.current;
|
||||
thinkingMessageIdRef.current = null;
|
||||
thinkingLogsRef.current = [];
|
||||
|
||||
// Remove ALL thinking messages (not just the one with current ID)
|
||||
// This handles cases where multiple thinking messages might exist
|
||||
setMessages(prevMessages => {
|
||||
return prevMessages.filter(m => m.status !== 'thinking');
|
||||
});
|
||||
}, []);
|
||||
|
||||
// Process logs from queue one by one (progressive display)
|
||||
|
|
@ -110,8 +113,8 @@ export function useChatbot() {
|
|||
|
||||
// Update messages immediately
|
||||
setMessages(prevMessages => {
|
||||
// Remove old thinking message if it exists
|
||||
const filtered = prevMessages.filter(m => m.id !== thinkingId);
|
||||
// Remove ALL thinking messages first (to prevent duplicates from previous workflows)
|
||||
const filtered = prevMessages.filter(m => m.status !== 'thinking');
|
||||
// Add updated thinking message
|
||||
const updated = [...filtered, thinkingMessage];
|
||||
return updated.sort(sortMessages);
|
||||
|
|
@ -129,7 +132,21 @@ export function useChatbot() {
|
|||
}, [workflowId]);
|
||||
|
||||
// Add a single log to thinking message (progressive display)
|
||||
const addLogToThinkingMessage = useCallback((logMessage: string) => {
|
||||
const addLogToThinkingMessage = useCallback((logMessage: string, createdAt?: number) => {
|
||||
// Create a unique key for this log message to detect duplicates
|
||||
// Use content + createdAt timestamp if available, otherwise use current time
|
||||
const timestamp = createdAt || Date.now();
|
||||
const logKey = `${logMessage.trim()}_${timestamp}`;
|
||||
|
||||
// Skip if this log was already processed
|
||||
if (processedLogsRef.current.has(logKey)) {
|
||||
console.log('[useChatbot] Skipping duplicate log:', logMessage.substring(0, 50) + '...');
|
||||
return;
|
||||
}
|
||||
|
||||
// Mark as processed
|
||||
processedLogsRef.current.add(logKey);
|
||||
|
||||
// Add log to queue
|
||||
logQueueRef.current.push(logMessage);
|
||||
|
||||
|
|
@ -141,14 +158,27 @@ export function useChatbot() {
|
|||
|
||||
// Process SSE event and update messages
|
||||
const processChatDataItem = useCallback((item: ChatDataItem) => {
|
||||
// Log the actual streamed response for debugging
|
||||
console.log('[useChatbot] Streamed item:', {
|
||||
type: item.type,
|
||||
createdAt: item.createdAt,
|
||||
item: item.item
|
||||
});
|
||||
|
||||
if (item.type === 'log' && item.item) {
|
||||
// Process log item - add to thinking message one at a time
|
||||
const logData = item.item as any;
|
||||
const logMessage = logData.message || logData.text || '';
|
||||
|
||||
console.log('[useChatbot] Processing log:', {
|
||||
message: logMessage.substring(0, 100) + (logMessage.length > 100 ? '...' : ''),
|
||||
createdAt: item.createdAt,
|
||||
fullItem: item
|
||||
});
|
||||
|
||||
if (logMessage) {
|
||||
// Add log immediately (progressive display)
|
||||
addLogToThinkingMessage(logMessage);
|
||||
// Add log immediately (progressive display) with createdAt for deduplication
|
||||
addLogToThinkingMessage(logMessage, item.createdAt);
|
||||
}
|
||||
} else if (item.type === 'message' && item.item) {
|
||||
const messageData = item.item as any;
|
||||
|
|
@ -170,38 +200,26 @@ export function useChatbot() {
|
|||
// Check if we've already processed this message
|
||||
const messageId = messageData.id;
|
||||
|
||||
// Always clear thinking messages when a real message arrives
|
||||
clearThinkingMessage();
|
||||
|
||||
if (processedMessageIdsRef.current.has(messageId)) {
|
||||
// Update existing message - clear thinking message first
|
||||
// Update existing message
|
||||
setMessages(prevMessages => {
|
||||
let filtered = prevMessages;
|
||||
if (thinkingId) {
|
||||
filtered = prevMessages.filter(m => m.id !== thinkingId);
|
||||
thinkingMessageIdRef.current = null;
|
||||
thinkingLogsRef.current = [];
|
||||
}
|
||||
|
||||
const existingIndex = filtered.findIndex(m => m.id === messageId);
|
||||
const existingIndex = prevMessages.findIndex(m => m.id === messageId);
|
||||
if (existingIndex >= 0) {
|
||||
const updated = [...filtered];
|
||||
const updated = [...prevMessages];
|
||||
updated[existingIndex] = messageData as Message;
|
||||
return updated.sort(sortMessages);
|
||||
}
|
||||
return filtered;
|
||||
return prevMessages;
|
||||
});
|
||||
} else {
|
||||
// Add new message - clear thinking message first
|
||||
// Add new message
|
||||
processedMessageIdsRef.current.add(messageId);
|
||||
setMessages(prevMessages => {
|
||||
// Remove thinking message BEFORE adding new message (same state update)
|
||||
let filtered = prevMessages;
|
||||
if (thinkingId) {
|
||||
filtered = prevMessages.filter(m => m.id !== thinkingId);
|
||||
thinkingMessageIdRef.current = null;
|
||||
thinkingLogsRef.current = [];
|
||||
}
|
||||
|
||||
// Add new message
|
||||
const updated = [...filtered, messageData as Message];
|
||||
// Add new message (thinking messages already cleared by clearThinkingMessage)
|
||||
const updated = [...prevMessages, messageData as Message];
|
||||
return updated.sort(sortMessages);
|
||||
});
|
||||
}
|
||||
|
|
@ -348,7 +366,6 @@ export function useChatbot() {
|
|||
setInputValue(value);
|
||||
}, []);
|
||||
|
||||
<<<<<<< HEAD
|
||||
// Handle file upload
|
||||
const handleFileUpload = useCallback(async (file: File): Promise<{ success: boolean; data?: any }> => {
|
||||
setUploadError(null);
|
||||
|
|
@ -416,8 +433,6 @@ export function useChatbot() {
|
|||
setUploadedFiles(prev => prev.filter(f => f.fileId !== fileId));
|
||||
}, []);
|
||||
|
||||
=======
|
||||
>>>>>>> c76e7efd28210f45737b5afbdddff2712b2c0cc7
|
||||
// Stop chatbot workflow
|
||||
const stopChatbot = useCallback(async () => {
|
||||
if (!workflowId || !isRunning) {
|
||||
|
|
@ -476,7 +491,6 @@ export function useChatbot() {
|
|||
const abortController = new AbortController();
|
||||
streamAbortControllerRef.current = abortController;
|
||||
|
||||
<<<<<<< HEAD
|
||||
// Use ref to get current file IDs (avoids closure issues)
|
||||
const fileIdsToSend = pendingFileIdsRef.current.length > 0
|
||||
? pendingFileIdsRef.current
|
||||
|
|
@ -487,15 +501,11 @@ export function useChatbot() {
|
|||
console.log('[handleSubmit] pendingFileIds from ref:', pendingFileIdsRef.current);
|
||||
console.log('[handleSubmit] fileIdsToSend:', fileIdsToSend);
|
||||
|
||||
=======
|
||||
// Prepare request body
|
||||
>>>>>>> c76e7efd28210f45737b5afbdddff2712b2c0cc7
|
||||
const requestBody: StartChatbotRequest = {
|
||||
prompt: trimmedInput,
|
||||
userLanguage: 'en',
|
||||
...(workflowId && { workflowId })
|
||||
};
|
||||
<<<<<<< HEAD
|
||||
|
||||
// Always include listFileId if there are any files
|
||||
if (fileIdsToSend.length > 0) {
|
||||
|
|
@ -506,14 +516,16 @@ export function useChatbot() {
|
|||
}
|
||||
|
||||
console.log('[handleSubmit] Final requestBody:', JSON.stringify(requestBody, null, 2));
|
||||
=======
|
||||
>>>>>>> c76e7efd28210f45737b5afbdddff2712b2c0cc7
|
||||
|
||||
// Track if workflow was created in this request
|
||||
let workflowCreated = false;
|
||||
|
||||
// Clear thinking message when starting a new request
|
||||
clearThinkingMessage();
|
||||
processedLogsRef.current.clear(); // Clear processed logs for new request
|
||||
|
||||
// Track if this is the first event (to reset isSubmitting)
|
||||
let firstEventReceived = false;
|
||||
|
||||
// Start SSE stream
|
||||
await startChatbotStreamApi(
|
||||
|
|
@ -524,6 +536,12 @@ export function useChatbot() {
|
|||
return;
|
||||
}
|
||||
|
||||
// Reset isSubmitting after first event to enable stop button
|
||||
if (!firstEventReceived) {
|
||||
firstEventReceived = true;
|
||||
setIsSubmitting(false);
|
||||
}
|
||||
|
||||
// Process the chat data item
|
||||
processChatDataItem(item);
|
||||
|
||||
|
|
@ -549,6 +567,15 @@ export function useChatbot() {
|
|||
console.error('SSE stream error:', err);
|
||||
setError(err.message || 'Stream error occurred');
|
||||
setIsRunning(false);
|
||||
// Reset isSubmitting if stream fails before first event
|
||||
if (!firstEventReceived) {
|
||||
setIsSubmitting(false);
|
||||
}
|
||||
// Clear thinking messages on error
|
||||
clearThinkingMessage();
|
||||
} else {
|
||||
// Stream was aborted (stopped) - clear thinking messages
|
||||
clearThinkingMessage();
|
||||
}
|
||||
},
|
||||
() => {
|
||||
|
|
@ -556,19 +583,19 @@ export function useChatbot() {
|
|||
if (!abortController.signal.aborted) {
|
||||
setIsRunning(false);
|
||||
setInputValue(''); // Clear input on completion
|
||||
<<<<<<< HEAD
|
||||
// Clear pending file IDs after successful submission (files are now part of conversation)
|
||||
setPendingFileIds([]);
|
||||
pendingFileIdsRef.current = []; // Clear ref too
|
||||
setUploadedFiles([]);
|
||||
=======
|
||||
>>>>>>> c76e7efd28210f45737b5afbdddff2712b2c0cc7
|
||||
// Clear thinking message on completion if no final message was received
|
||||
// Clear thinking message on completion (final message should have cleared it, but ensure cleanup)
|
||||
clearThinkingMessage();
|
||||
// Refresh threads list after message completion (silently, without loading state)
|
||||
setTimeout(() => {
|
||||
clearThinkingMessage();
|
||||
// Refresh threads list after message completion (silently, without loading state)
|
||||
loadThreadsSilently();
|
||||
}, 100);
|
||||
} else {
|
||||
// Stream was aborted (stopped) - clear thinking messages
|
||||
clearThinkingMessage();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
@ -581,15 +608,13 @@ export function useChatbot() {
|
|||
console.error('Error starting chatbot:', err);
|
||||
setError(err.message || 'Failed to start chatbot');
|
||||
setIsRunning(false);
|
||||
// Clear thinking messages on error
|
||||
clearThinkingMessage();
|
||||
} finally {
|
||||
setIsSubmitting(false);
|
||||
streamAbortControllerRef.current = null;
|
||||
}
|
||||
<<<<<<< HEAD
|
||||
}, [inputValue, workflowId, isRunning, isSubmitting, stopChatbot, processChatDataItem, clearThinkingMessage, loadThreads, pendingFileIds]);
|
||||
=======
|
||||
}, [inputValue, workflowId, isRunning, isSubmitting, stopChatbot, processChatDataItem, clearThinkingMessage, loadThreads]);
|
||||
>>>>>>> c76e7efd28210f45737b5afbdddff2712b2c0cc7
|
||||
|
||||
// Delete a chatbot workflow
|
||||
const handleDeleteThread = useCallback(async (workflowIdToDelete: string): Promise<boolean> => {
|
||||
|
|
@ -649,14 +674,12 @@ export function useChatbot() {
|
|||
setSelectedThreadId(null);
|
||||
setError(null);
|
||||
setInputValue('');
|
||||
<<<<<<< HEAD
|
||||
setPendingFileIds([]);
|
||||
pendingFileIdsRef.current = [];
|
||||
setUploadedFiles([]);
|
||||
=======
|
||||
>>>>>>> c76e7efd28210f45737b5afbdddff2712b2c0cc7
|
||||
thinkingLogsRef.current = [];
|
||||
thinkingMessageIdRef.current = null;
|
||||
processedLogsRef.current.clear();
|
||||
clearProcessedMessages();
|
||||
}, [clearProcessedMessages]);
|
||||
|
||||
|
|
@ -675,14 +698,12 @@ export function useChatbot() {
|
|||
setIsSubmitting(false);
|
||||
setError(null);
|
||||
setInputValue('');
|
||||
<<<<<<< HEAD
|
||||
setPendingFileIds([]);
|
||||
pendingFileIdsRef.current = [];
|
||||
setUploadedFiles([]);
|
||||
=======
|
||||
>>>>>>> c76e7efd28210f45737b5afbdddff2712b2c0cc7
|
||||
thinkingLogsRef.current = [];
|
||||
thinkingMessageIdRef.current = null;
|
||||
processedLogsRef.current.clear();
|
||||
clearProcessedMessages();
|
||||
}, [clearProcessedMessages]);
|
||||
|
||||
|
|
@ -694,6 +715,7 @@ export function useChatbot() {
|
|||
}
|
||||
logQueueRef.current = [];
|
||||
isProcessingLogsRef.current = false;
|
||||
processedLogsRef.current.clear();
|
||||
}, []);
|
||||
|
||||
// Memoized display messages
|
||||
|
|
@ -740,7 +762,6 @@ export function useChatbot() {
|
|||
stopChatbot,
|
||||
resetChatbot,
|
||||
startNewChat,
|
||||
<<<<<<< HEAD
|
||||
cleanup,
|
||||
|
||||
// File upload interface
|
||||
|
|
@ -751,9 +772,6 @@ export function useChatbot() {
|
|||
uploadedFiles,
|
||||
uploadingFile,
|
||||
uploadError
|
||||
=======
|
||||
cleanup
|
||||
>>>>>>> c76e7efd28210f45737b5afbdddff2712b2c0cc7
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue