From 276cc8d23a1e73db1b9447148455a7f78c034d94 Mon Sep 17 00:00:00 2001 From: Louis Knight-Webb Date: Tue, 24 Jun 2025 01:16:39 +0100 Subject: [PATCH] Better error handling for follow ups --- backend/src/routes/task_attempts.rs | 41 +++++++++---------- .../src/components/tasks/TaskDetailsPanel.tsx | 21 ++++++++-- 2 files changed, 36 insertions(+), 26 deletions(-) diff --git a/backend/src/routes/task_attempts.rs b/backend/src/routes/task_attempts.rs index 60cfbcef..5d6891f7 100644 --- a/backend/src/routes/task_attempts.rs +++ b/backend/src/routes/task_attempts.rs @@ -766,34 +766,31 @@ pub async fn create_followup_attempt( return Err(StatusCode::NOT_FOUND); } - // Start follow-up execution asynchronously - let pool_clone = pool.clone(); - let app_state_clone = app_state.clone(); - let prompt = payload.prompt.clone(); - tokio::spawn(async move { - if let Err(e) = TaskAttempt::start_followup_execution( - &pool_clone, - &app_state_clone, - attempt_id, - task_id, - project_id, - &prompt, - ) - .await - { + // Start follow-up execution synchronously to catch errors + match TaskAttempt::start_followup_execution( + &pool, + &app_state, + attempt_id, + task_id, + project_id, + &payload.prompt, + ) + .await + { + Ok(_) => Ok(ResponseJson(ApiResponse { + success: true, + data: Some("Follow-up execution started successfully".to_string()), + message: Some("Follow-up execution started successfully".to_string()), + })), + Err(e) => { tracing::error!( "Failed to start follow-up execution for task attempt {}: {}", attempt_id, e ); + Err(StatusCode::INTERNAL_SERVER_ERROR) } - }); - - Ok(ResponseJson(ApiResponse { - success: true, - data: Some("Follow-up execution started successfully".to_string()), - message: Some("Follow-up execution started successfully".to_string()), - })) + } } pub fn task_attempts_router() -> Router { diff --git a/frontend/src/components/tasks/TaskDetailsPanel.tsx b/frontend/src/components/tasks/TaskDetailsPanel.tsx index 9e762472..edd21f55 100644 --- a/frontend/src/components/tasks/TaskDetailsPanel.tsx +++ b/frontend/src/components/tasks/TaskDetailsPanel.tsx @@ -13,9 +13,10 @@ import { Trash2, StopCircle, Send, + AlertCircle, } from "lucide-react"; import { Button } from "@/components/ui/button"; - +import { Alert, AlertDescription } from "@/components/ui/alert"; import { Label } from "@/components/ui/label"; import { Chip } from "@/components/ui/chip"; import { Textarea } from "@/components/ui/textarea"; @@ -150,6 +151,7 @@ export function TaskDetailsPanel({ const [showEditorDialog, setShowEditorDialog] = useState(false); const [followUpMessage, setFollowUpMessage] = useState(""); const [isSendingFollowUp, setIsSendingFollowUp] = useState(false); + const [followUpError, setFollowUpError] = useState(null); const { config } = useConfig(); // Available executors @@ -433,6 +435,7 @@ export function TaskDetailsPanel({ try { setIsSendingFollowUp(true); + setFollowUpError(null); const response = await makeRequest( `/api/projects/${projectId}/tasks/${task.id}/attempts/${selectedAttempt.id}/follow-up`, { @@ -452,10 +455,11 @@ export function TaskDetailsPanel({ // Refresh activities to show the new follow-up execution fetchAttemptActivities(selectedAttempt.id); } else { - console.error("Failed to send follow-up:", await response.text()); + const errorText = await response.text(); + setFollowUpError(`Failed to start follow-up execution: ${errorText || response.statusText}`); } } catch (err) { - console.error("Failed to send follow-up:", err); + setFollowUpError(`Failed to send follow-up: ${err instanceof Error ? err.message : 'Unknown error'}`); } finally { setIsSendingFollowUp(false); } @@ -844,11 +848,20 @@ export function TaskDetailsPanel({ + {followUpError && ( + + + {followUpError} + + )}