Spaces:
Sleeping
Sleeping
| /** | |
| * useAIHealthCheck.ts — Hook per testare la latenza dei provider AI via backend | |
| * | |
| * Chiama GET /api/ai/health (FastAPI HF Space) che esegue probe parallelo | |
| * su tutti i provider configurati (openrouter, gemini, groq, hf). | |
| * Cache in-memory 60s lato client — non chiama il backend ad ogni render. | |
| * | |
| * Usage: | |
| * const { data, loading, error, refresh } = useAIHealthCheck(); | |
| * | |
| * Distinto da useProviderHealth (Sessione 8) che monitora il runtime locale. | |
| */ | |
| import { useState, useCallback, useRef } from "react"; | |
| import { makeTimedSignal } from "@/lib/agentLoop/networkConstants"; // Loop-12: iOS-safe | |
| const _BACKEND = (import.meta.env.VITE_BACKEND_URL ?? "").replace(/\/$/, ""); | |
| const CACHE_TTL_MS = 60_000; | |
| export interface AIProviderResult { | |
| name: string; | |
| ok: boolean; | |
| latency_ms: number; | |
| model: string; | |
| error?: string; | |
| } | |
| export interface AIHealthData { | |
| providers: AIProviderResult[]; | |
| tested_at: number; | |
| } | |
| export function useAIHealthCheck() { | |
| const [data, setData] = useState<AIHealthData | null>(null); | |
| const [loading, setLoading] = useState(false); | |
| const [error, setError] = useState<string | null>(null); | |
| const cacheRef = useRef<{ data: AIHealthData; at: number } | null>(null); | |
| const refresh = useCallback(async (force = false) => { | |
| if (!_BACKEND) { | |
| setError("VITE_BACKEND_URL non configurato"); | |
| return; | |
| } | |
| // Cache hit (skip se force=true) | |
| if (!force && cacheRef.current && Date.now() - cacheRef.current.at < CACHE_TTL_MS) { | |
| setData(cacheRef.current.data); | |
| return; | |
| } | |
| setLoading(true); | |
| setError(null); | |
| try { | |
| const res = await fetch(`${_BACKEND}/api/ai/health`, { | |
| signal: makeTimedSignal(15_000), | |
| }); | |
| if (!res.ok) throw new Error(`HTTP ${res.status}`); | |
| const json = (await res.json()) as AIHealthData; | |
| cacheRef.current = { data: json, at: Date.now() }; | |
| setData(json); | |
| } catch (err: unknown) { | |
| setError((err as Error).message ?? "Errore sconosciuto"); | |
| } finally { | |
| setLoading(false); | |
| } | |
| }, []); | |
| return { data, loading, error, refresh }; | |
| } | |