diff --git a/backend/app/service/chat_service.py b/backend/app/service/chat_service.py index 5e17be91e..56c1fe704 100644 --- a/backend/app/service/chat_service.py +++ b/backend/app/service/chat_service.py @@ -428,6 +428,8 @@ async def step_solve(options: Chat, request: Request, task_lock: TaskLock): # Check if this might be a misrouted second question if camel_task is None and workforce is None: + logger.error(f"Cannot add task: both camel_task and workforce are None for project {options.project_id}") + yield sse_json("error", {"message": "Cannot add task: task not initialized. Please start a task first."}) continue assert camel_task is not None diff --git a/src/components/ChatBox/index.tsx b/src/components/ChatBox/index.tsx index e2321fac5..fd9f6fd11 100644 --- a/src/components/ChatBox/index.tsx +++ b/src/components/ChatBox/index.tsx @@ -168,9 +168,6 @@ export default function ChatBox(): JSX.Element { chatStore.setAttaches(_taskId, []); // Clear attaches after queuing setMessage(""); if (textareaRef.current) textareaRef.current.style.height = "60px"; - toast.success("Task queued. It will be processed when the current task finishes.", { - closeButton: true, - }); //Send the task as soon as possible //Workforce internal queue handles it @@ -185,9 +182,17 @@ export default function ChatBox(): JSX.Element { timestamp: Date.now() } }); + + // Only show success toast after API call succeeds + toast.success("Task queued. It will be processed when the current task finishes.", { + closeButton: true, + }); } catch (error) { console.error(`Removing Message "${tempMessageContent}..." due to ${error}`) projectStore.removeQueuedMessage(project_id as string, new_task_id); + toast.error("Failed to queue task. Please try again.", { + closeButton: true, + }); } return; } @@ -591,14 +596,21 @@ export default function ChatBox(): JSX.Element { //Optimistic Removal projectStore.removeQueuedMessage(project_id, task_id); - //Call api only when workforce has been run at least once - //Note: Replay creates a new chatstore, so no conflicts + // Always try to call the backend to remove the task + // The backend will handle the error gracefully if workforce is not initialized + // Note: Replay creates a new chatstore, so no conflicts const task = chatStore.tasks[chatStore.activeTaskId as string]; - if(task.messages && task.messages.some(m => m.step === 'to_sub_tasks') && task.status === "running") { - await fetchDelete(`/chat/${project_id}/remove-task/${task_id}`, { - project_id: project_id, - task_id: task_id - }); + // Only skip backend call if task is finished or hasn't started yet (no messages) + if(task && task.messages.length > 0 && task.status !== 'finished') { + try { + await fetchDelete(`/chat/${project_id}/remove-task/${task_id}`, { + project_id: project_id, + task_id: task_id + }); + } catch (apiError) { + // If backend returns an error, it's okay - the task might not be in the workforce queue yet + console.log(`Backend remove call failed (expected if workforce not started): ${apiError}`); + } } } catch (error) { // Revert the optimistic removal by restoring the original message