AUDIT / src /hooks /useAIHealthCheck.ts
Arypulka98's picture
feat(audit): deploy full backend cluster node (part 2)
cc11e77 verified
Raw
History Blame Contribute Delete
2.15 kB
/**
* 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 };
}