Spaces:
Running
Running
| "use client"; | |
| import { useState, useEffect, useCallback } from "react"; | |
| // API server runs on port 7860 | |
| const API_BASE = "http://localhost:7860"; | |
| interface UseSessionReturn { | |
| isActive: boolean; // Whether session is running | |
| isLoading: boolean; // Initial fetch in progress | |
| isToggling: boolean; // Stop/start in progress | |
| provider: string | null; // Current provider | |
| toggle: () => Promise<void>; | |
| stop: () => Promise<void>; | |
| start: () => Promise<void>; | |
| } | |
| export function useSession(): UseSessionReturn { | |
| const [isActive, setIsActive] = useState(false); // Start inactive - user clicks "Start Session" | |
| const [isLoading, setIsLoading] = useState(true); | |
| const [isToggling, setIsToggling] = useState(false); | |
| const [provider, setProvider] = useState<string | null>(null); | |
| const fetchSessionState = useCallback(async () => { | |
| try { | |
| const response = await fetch(`${API_BASE}/api/session`); | |
| if (response.ok) { | |
| const data = await response.json(); | |
| setIsActive(data.active); | |
| setProvider(data.provider); | |
| } | |
| } catch (error) { | |
| console.error("Failed to fetch session state:", error); | |
| } finally { | |
| setIsLoading(false); | |
| } | |
| }, []); | |
| const stop = useCallback(async () => { | |
| setIsToggling(true); | |
| try { | |
| const response = await fetch(`${API_BASE}/api/session`, { | |
| method: "POST", | |
| headers: { "Content-Type": "application/json" }, | |
| body: JSON.stringify({ active: false }), | |
| }); | |
| if (response.ok) { | |
| const data = await response.json(); | |
| setIsActive(data.active); | |
| } | |
| } catch (error) { | |
| console.error("Failed to stop session:", error); | |
| } finally { | |
| setIsToggling(false); | |
| } | |
| }, []); | |
| const start = useCallback(async () => { | |
| setIsToggling(true); | |
| try { | |
| const response = await fetch(`${API_BASE}/api/session`, { | |
| method: "POST", | |
| headers: { "Content-Type": "application/json" }, | |
| body: JSON.stringify({ active: true }), | |
| }); | |
| if (response.ok) { | |
| const data = await response.json(); | |
| setIsActive(data.active); | |
| if (data.provider) { | |
| setProvider(data.provider); | |
| } | |
| } | |
| } catch (error) { | |
| console.error("Failed to start session:", error); | |
| } finally { | |
| setIsToggling(false); | |
| } | |
| }, []); | |
| const toggle = useCallback(async () => { | |
| if (isActive) { | |
| await stop(); | |
| } else { | |
| await start(); | |
| } | |
| }, [isActive, stop, start]); | |
| useEffect(() => { | |
| fetchSessionState(); | |
| }, [fetchSessionState]); | |
| // Re-fetch session state when wakeword or end-session events arrive via WebSocket | |
| useEffect(() => { | |
| const handleLifecycle = () => { | |
| fetchSessionState(); | |
| }; | |
| window.addEventListener("session-lifecycle", handleLifecycle); | |
| return () => window.removeEventListener("session-lifecycle", handleLifecycle); | |
| }, [fetchSessionState]); | |
| return { | |
| isActive, | |
| isLoading, | |
| isToggling, | |
| provider, | |
| toggle, | |
| stop, | |
| start, | |
| }; | |
| } | |