diff --git a/frontend/app/onboarding/_components/onboarding-upload.tsx b/frontend/app/onboarding/_components/onboarding-upload.tsx index 263af7b7..ce7a0f91 100644 --- a/frontend/app/onboarding/_components/onboarding-upload.tsx +++ b/frontend/app/onboarding/_components/onboarding-upload.tsx @@ -158,6 +158,16 @@ const OnboardingUpload = ({ onComplete }: OnboardingUploadProps) => { const errorMessage = error instanceof Error ? error.message : "Upload failed"; console.error("Upload failed", errorMessage); + // Dispatch event that chat context can listen to + // This avoids circular dependency issues + if (typeof window !== "undefined") { + window.dispatchEvent( + new CustomEvent("ingestionFailed", { + detail: { source: "onboarding" }, + }), + ); + } + // Show error toast notification toast.error("Document upload failed", { description: errorMessage, diff --git a/frontend/components/knowledge-dropdown.tsx b/frontend/components/knowledge-dropdown.tsx index d0100790..932eb974 100644 --- a/frontend/components/knowledge-dropdown.tsx +++ b/frontend/components/knowledge-dropdown.tsx @@ -238,6 +238,15 @@ export function KnowledgeDropdown() { await uploadFileUtil(file, replace); refetchTasks(); } catch (error) { + // Dispatch event that chat context can listen to + // This avoids circular dependency issues + if (typeof window !== "undefined") { + window.dispatchEvent( + new CustomEvent("ingestionFailed", { + detail: { source: "knowledge-dropdown" }, + }), + ); + } toast.error("Upload failed", { description: error instanceof Error ? error.message : "Unknown error", }); diff --git a/frontend/contexts/chat-context.tsx b/frontend/contexts/chat-context.tsx index 46c8a2f8..59b5edeb 100644 --- a/frontend/contexts/chat-context.tsx +++ b/frontend/contexts/chat-context.tsx @@ -112,6 +112,18 @@ export function ChatProvider({ children }: ChatProviderProps) { useState(null); const [hasChatError, setChatError] = useState(false); + // Listen for ingestion failures and set chat error flag + useEffect(() => { + const handleIngestionFailed = () => { + setChatError(true); + }; + + window.addEventListener("ingestionFailed", handleIngestionFailed); + return () => { + window.removeEventListener("ingestionFailed", handleIngestionFailed); + }; + }, []); + // Debounce refresh requests to prevent excessive reloads const refreshTimeoutRef = useRef(null); diff --git a/frontend/contexts/task-context.tsx b/frontend/contexts/task-context.tsx index 97cdddf1..780bbc7e 100644 --- a/frontend/contexts/task-context.tsx +++ b/frontend/contexts/task-context.tsx @@ -323,6 +323,20 @@ export function TaskProvider({ children }: { children: React.ReactNode }) { currentTask.error || "Unknown error" }`, }); + + // Set chat error flag to trigger test_completion=true on health checks + // Only for ingestion-related tasks (tasks with files are ingestion tasks) + if (currentTask.files && Object.keys(currentTask.files).length > 0) { + // Dispatch event that chat context can listen to + // This avoids circular dependency issues + if (typeof window !== "undefined") { + window.dispatchEvent( + new CustomEvent("ingestionFailed", { + detail: { taskId: currentTask.task_id }, + }), + ); + } + } } } });