From 52dfdb191358dc1b93ec8e7e8225dbb7553be77a Mon Sep 17 00:00:00 2001 From: Mohamed Boudra Date: Tue, 7 Apr 2026 14:17:52 +0700 Subject: [PATCH] fix(app): use shared provider snapshot hook in settings and add refresh button Settings providers section now uses useProvidersSnapshot instead of a one-shot fetch, so it shares the same real-time data source as the status bar and draft form. Adds a Refresh button to re-detect installed provider CLIs without restarting the daemon. --- packages/app/src/screens/settings-screen.tsx | 58 +++++++++----------- 1 file changed, 26 insertions(+), 32 deletions(-) diff --git a/packages/app/src/screens/settings-screen.tsx b/packages/app/src/screens/settings-screen.tsx index bb6b2ace6..796c21bf2 100644 --- a/packages/app/src/screens/settings-screen.tsx +++ b/packages/app/src/screens/settings-screen.tsx @@ -62,12 +62,12 @@ import { settingsStyles } from "@/styles/settings"; import { THINKING_TONE_NATIVE_PCM_BASE64 } from "@/utils/thinking-tone.native-pcm"; import { useVoiceAudioEngineOptional } from "@/contexts/voice-context"; import { useIsLocalDaemon } from "@/hooks/use-is-local-daemon"; +import { useProvidersSnapshot } from "@/hooks/use-providers-snapshot"; import { isCompactFormFactor } from "@/constants/layout"; import { AGENT_PROVIDER_DEFINITIONS } from "@server/server/agent/provider-manifest"; import { getProviderIcon } from "@/components/provider-icons"; import { ProviderDiagnosticSheet } from "@/components/provider-diagnostic-sheet"; import { StatusBadge } from "@/components/ui/status-badge"; -import type { ProviderSnapshotEntry } from "@server/server/agent/agent-sdk-types"; // --------------------------------------------------------------------------- // Section definitions @@ -432,55 +432,49 @@ interface ProvidersSectionProps { function ProvidersSection({ routeServerId }: ProvidersSectionProps) { const { theme } = useUnistyles(); - const client = useHostRuntimeClient(routeServerId); const isConnected = useHostRuntimeIsConnected(routeServerId); - const [entries, setEntries] = useState([]); - const [loading, setLoading] = useState(false); + const { entries, isLoading, isFetching, refresh } = useProvidersSnapshot(routeServerId); const [diagnosticProvider, setDiagnosticProvider] = useState(null); - useEffect(() => { - if (!client || !isConnected) { - setEntries([]); - return; - } - - let cancelled = false; - setLoading(true); - client - .getProvidersSnapshot() - .then((result) => { - if (!cancelled) setEntries(result.entries); - }) - .catch(() => { - if (!cancelled) setEntries([]); - }) - .finally(() => { - if (!cancelled) setLoading(false); - }); - - return () => { - cancelled = true; - }; - }, [client, isConnected]); - const hasServer = routeServerId.length > 0; return ( <> - Providers + + Providers + {hasServer && isConnected ? ( + + + Refresh + + + ) : null} + {!hasServer || !isConnected ? ( Connect to a host to see providers - ) : loading ? ( + ) : isLoading ? ( Loading... ) : ( {AGENT_PROVIDER_DEFINITIONS.map((def) => { - const entry = entries.find((e) => e.provider === def.id); + const entry = entries?.find((e) => e.provider === def.id); const status = entry?.status ?? "unavailable"; const ProviderIcon = getProviderIcon(def.id);