diff --git a/surfsense_backend/app/tasks/chat/stream_new_chat.py b/surfsense_backend/app/tasks/chat/stream_new_chat.py index 11024e513..69b75e5c4 100644 --- a/surfsense_backend/app/tasks/chat/stream_new_chat.py +++ b/surfsense_backend/app/tasks/chat/stream_new_chat.py @@ -590,58 +590,6 @@ async def stream_new_chat( else {"input": tool_input}, ) - # Send terminal info about the tool call - if tool_name == "search_knowledge_base": - query = ( - tool_input.get("query", "") - if isinstance(tool_input, dict) - else str(tool_input) - ) - yield streaming_service.format_terminal_info( - f"Searching knowledge base: {query[:100]}{'...' if len(query) > 100 else ''}", - "info", - ) - elif tool_name == "link_preview": - url = ( - tool_input.get("url", "") - if isinstance(tool_input, dict) - else str(tool_input) - ) - yield streaming_service.format_terminal_info( - f"Fetching link preview: {url[:80]}{'...' if len(url) > 80 else ''}", - "info", - ) - elif tool_name == "display_image": - src = ( - tool_input.get("src", "") - if isinstance(tool_input, dict) - else str(tool_input) - ) - yield streaming_service.format_terminal_info( - f"Analyzing image: {src[:60]}{'...' if len(src) > 60 else ''}", - "info", - ) - elif tool_name == "scrape_webpage": - url = ( - tool_input.get("url", "") - if isinstance(tool_input, dict) - else str(tool_input) - ) - yield streaming_service.format_terminal_info( - f"Scraping webpage: {url[:70]}{'...' if len(url) > 70 else ''}", - "info", - ) - elif tool_name == "generate_podcast": - title = ( - tool_input.get("podcast_title", "SurfSense Podcast") - if isinstance(tool_input, dict) - else "SurfSense Podcast" - ) - yield streaming_service.format_terminal_info( - f"Generating podcast: {title}", - "info", - ) - elif event_type == "on_tool_end": run_id = event.get("run_id", "") tool_name = event.get("name", "unknown_tool") diff --git a/surfsense_web/app/dashboard/[search_space_id]/documents/(manage)/page.tsx b/surfsense_web/app/dashboard/[search_space_id]/documents/(manage)/page.tsx index edfda7dbf..482c4594d 100644 --- a/surfsense_web/app/dashboard/[search_space_id]/documents/(manage)/page.tsx +++ b/surfsense_web/app/dashboard/[search_space_id]/documents/(manage)/page.tsx @@ -134,8 +134,11 @@ export default function DocumentsTable() { toast.success(t("refresh_success") || "Documents refreshed"); }, [debouncedSearch, refetchSearch, refetchDocuments, t]); - // Set up polling for active tasks - const { summary } = useLogsSummary(searchSpaceId, 24, { refetchInterval: 5000 }); + // Set up smart polling for active tasks - only polls when tasks are in progress + const { summary } = useLogsSummary(searchSpaceId, 24, { + enablePolling: true, + refetchInterval: 5000, // Poll every 5 seconds when tasks are active + }); const activeTasksCount = summary?.active_tasks.length || 0; const prevActiveTasksCount = useRef(activeTasksCount); diff --git a/surfsense_web/components/sidebar/nav-notes.tsx b/surfsense_web/components/sidebar/nav-notes.tsx index 3b03edb9c..c308e7c49 100644 --- a/surfsense_web/components/sidebar/nav-notes.tsx +++ b/surfsense_web/components/sidebar/nav-notes.tsx @@ -80,8 +80,10 @@ export function NavNotes({ const [isAllNotesSidebarOpen, setIsAllNotesSidebarOpen] = useState(false); // Poll for active reindexing tasks to show inline loading indicators + // Smart polling: only polls when there are active tasks, stops when idle const { summary } = useLogsSummary(searchSpaceId ? Number(searchSpaceId) : 0, 24, { - refetchInterval: 2000, + enablePolling: true, + refetchInterval: 5000, // Poll every 5 seconds when tasks are active }); // Create a Set of document IDs that are currently being reindexed diff --git a/surfsense_web/hooks/use-logs.ts b/surfsense_web/hooks/use-logs.ts index 41b2660e5..bee9a1955 100644 --- a/surfsense_web/hooks/use-logs.ts +++ b/surfsense_web/hooks/use-logs.ts @@ -118,12 +118,15 @@ export function useLogs(searchSpaceId?: number, filters: LogFilters = {}) { }; } -// Separate hook for log summary with optional polling support for document processing indicator UI +// Separate hook for log summary with smart polling support for document processing indicator UI +// Polling only happens when there are active tasks, otherwise it stops to save resources export function useLogsSummary( searchSpaceId: number, hours: number = 24, - options: { refetchInterval?: number } = {} + options: { refetchInterval?: number; enablePolling?: boolean } = {} ) { + const { enablePolling = false, refetchInterval = 10000 } = options; + const { data: summary, isLoading: loading, @@ -138,9 +141,20 @@ export function useLogsSummary( }), enabled: !!searchSpaceId, staleTime: 3 * 60 * 1000, - // Enable refetch interval for document processing indicator polling - refetchInterval: - options.refetchInterval && options.refetchInterval > 0 ? options.refetchInterval : undefined, + // Smart polling: only poll when there are active tasks and polling is enabled + // This prevents unnecessary API calls when nothing is being processed + refetchInterval: enablePolling + ? (query) => { + const data = query.state.data; + // Only continue polling if there are active tasks + if (data?.active_tasks && data.active_tasks.length > 0) { + return refetchInterval; + } + // No active tasks - stop polling but check again after a longer interval + // to catch any newly started tasks + return 30000; // Check every 30 seconds when idle + } + : undefined, }); return { summary, loading, error, refreshSummary: refetch };