diff --git a/apps/web/src/components/family/family-panel.tsx b/apps/web/src/components/family/family-panel.tsx
index e97aa1e..85dea55 100644
--- a/apps/web/src/components/family/family-panel.tsx
+++ b/apps/web/src/components/family/family-panel.tsx
@@ -9,11 +9,15 @@ type TabType = 'overview' | 'members' | 'availability' | 'settings';
interface FamilyPanelProps {
familyId: string;
+ /** When true, enables polling for family data updates (during agent conversation) */
+ isPolling?: boolean;
}
-export function FamilyPanel({ familyId }: FamilyPanelProps) {
+export function FamilyPanel({ familyId, isPolling = false }: FamilyPanelProps) {
const [activeTab, setActiveTab] = useState('overview');
- const { family, members, availability, settings, isLoading, error } = useFamilyData(familyId);
+ const { family, members, availability, settings, isLoading, error } = useFamilyData(familyId, {
+ isPolling,
+ });
const tabs: { id: TabType; label: string }[] = [
{ id: 'overview', label: 'Overview' },
diff --git a/apps/web/src/hooks/use-chat.ts b/apps/web/src/hooks/use-chat.ts
index 0461815..c531910 100644
--- a/apps/web/src/hooks/use-chat.ts
+++ b/apps/web/src/hooks/use-chat.ts
@@ -1,10 +1,12 @@
-import { useState, useRef, useEffect } from 'react';
+import { useState, useRef, useEffect, useCallback } from 'react';
export interface Message {
role: 'user' | 'assistant';
content: string;
}
+const POLLING_DURATION_MS = 5000; // Duration to poll after receiving a message
+
export function useChat() {
const [messages, setMessages] = useState([]);
const [input, setInput] = useState('');
@@ -18,6 +20,36 @@ export function useChat() {
// Family ID state - will be set when agent creates a family
const [familyId, setFamilyId] = useState(null);
+ // Polling state - controls when family data should be polled
+ const [isPolling, setIsPolling] = useState(false);
+ const pollingTimeoutRef = useRef | null>(null);
+
+ // Start or reset the polling timer
+ const triggerPolling = useCallback(() => {
+ // Clear existing timeout if any
+ if (pollingTimeoutRef.current) {
+ clearTimeout(pollingTimeoutRef.current);
+ }
+
+ // Enable polling
+ setIsPolling(true);
+
+ // Set timeout to disable polling after the duration
+ pollingTimeoutRef.current = setTimeout(() => {
+ setIsPolling(false);
+ pollingTimeoutRef.current = null;
+ }, POLLING_DURATION_MS);
+ }, []);
+
+ // Clean up timeout on unmount
+ useEffect(() => {
+ return () => {
+ if (pollingTimeoutRef.current) {
+ clearTimeout(pollingTimeoutRef.current);
+ }
+ };
+ }, []);
+
const scrollToBottom = () => {
messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
};
@@ -98,6 +130,9 @@ export function useChat() {
newMessages[newMessages.length - 1] = { ...assistantMessage };
return newMessages;
});
+ // Trigger polling when receiving agent messages
+ // This resets the 5s timer on each chunk received
+ triggerPolling();
} else if (data.type === 'error') {
throw new Error(data.content);
}
@@ -135,5 +170,7 @@ export function useChat() {
setInput,
familyId,
setFamilyId: updateFamilyId,
+ /** Whether family data polling is currently active (5s after last agent message) */
+ isPolling,
};
}
diff --git a/apps/web/src/hooks/use-family-data.ts b/apps/web/src/hooks/use-family-data.ts
index adc6880..dc0488b 100644
--- a/apps/web/src/hooks/use-family-data.ts
+++ b/apps/web/src/hooks/use-family-data.ts
@@ -1,33 +1,45 @@
import { useQuery } from '@tanstack/react-query';
import { apiClient } from '@/lib/api-client';
-export function useFamilyData(familyId: string) {
+interface UseFamilyDataOptions {
+ /** When true, enables polling every 1 second. When false, polling is disabled. */
+ isPolling?: boolean;
+}
+
+const POLLING_INTERVAL = 1000; // Poll every 1 second when active
+
+export function useFamilyData(familyId: string, options: UseFamilyDataOptions = {}) {
+ const { isPolling = false } = options;
+
+ // Only poll when isPolling is true, otherwise disable refetchInterval
+ const refetchInterval = isPolling ? POLLING_INTERVAL : false;
+
const familyQuery = useQuery({
queryKey: ['family', familyId],
queryFn: () => apiClient.getFamily(familyId),
enabled: !!familyId,
- refetchInterval: 5000, // Poll every 5 seconds for real-time updates
+ refetchInterval,
});
const membersQuery = useQuery({
queryKey: ['members', familyId],
queryFn: () => apiClient.getMembers(familyId),
enabled: !!familyId,
- refetchInterval: 5000,
+ refetchInterval,
});
const availabilityQuery = useQuery({
queryKey: ['availability', familyId],
queryFn: () => apiClient.getAvailability(familyId),
enabled: !!familyId,
- refetchInterval: 5000,
+ refetchInterval,
});
const settingsQuery = useQuery({
queryKey: ['settings', familyId],
queryFn: () => apiClient.getSettings(familyId),
enabled: !!familyId,
- refetchInterval: 5000,
+ refetchInterval,
});
return {