import { useState, useCallback, useEffect, useRef } from 'react' import type { ChatResponse, Metrics, TeachResponse, MemorySamples, Stats } from '../types' const API_BASE = import.meta.env.DEV ? '' : '' async function fetchJson(url: string, options?: RequestInit): Promise { const res = await fetch(`${API_BASE}${url}`, { headers: { 'Content-Type': 'application/json' }, ...options, }) if (!res.ok) throw new Error(`API ${url}: ${res.status}`) return res.json() } export function useApi() { const [connected, setConnected] = useState(false) const [metrics, setMetrics] = useState(null) const [stats, setStats] = useState(null) const [memorySamples, setMemorySamples] = useState(null) const [loading, setLoading] = useState(false) const pollRef = useRef(null) const checkHealth = useCallback(async () => { try { await fetchJson('/health') setConnected(true) } catch { setConnected(false) } }, []) const refreshMetrics = useCallback(async () => { try { const m = await fetchJson('/metrics') setMetrics(m) const s = await fetchJson('/stats') setStats(s) const ms = await fetchJson('/memory/samples?limit=100') setMemorySamples(ms) setConnected(true) } catch { setConnected(false) } }, []) const sendMessage = useCallback(async ( message: string, temperature?: number, maxTokens?: number ): Promise => { setLoading(true) try { const resp = await fetchJson('/chat', { method: 'POST', body: JSON.stringify({ message, temperature: temperature ?? 0.3, max_tokens: maxTokens ?? 200, }), }) // refresh metrics after each message refreshMetrics() return resp } finally { setLoading(false) } }, [refreshMetrics]) const teachModel = useCallback(async ( question: string, answer: string ): Promise => { setLoading(true) try { const resp = await fetchJson('/teach', { method: 'POST', body: JSON.stringify({ question, answer }), }) refreshMetrics() return resp } finally { setLoading(false) } }, [refreshMetrics]) const learnText = useCallback(async (text: string): Promise => { setLoading(true) try { const resp = await fetchJson('/learn-text', { method: 'POST', body: JSON.stringify({ text }), }) refreshMetrics() return resp } finally { setLoading(false) } }, [refreshMetrics]) const dream = useCallback(async (cycles: number): Promise => { setLoading(true) try { const resp = await fetchJson('/dream', { method: 'POST', body: JSON.stringify({ cycles, replay_batch: 200 }), }) refreshMetrics() return resp } finally { setLoading(false) } }, [refreshMetrics]) const reason = useCallback(async (question: string): Promise => { setLoading(true) try { const resp = await fetchJson('/reason', { method: 'POST', body: JSON.stringify({ message: question }), }) return resp } finally { setLoading(false) } }, []) // poll metrics every 5s useEffect(() => { checkHealth() refreshMetrics() pollRef.current = window.setInterval(() => { refreshMetrics() }, 5000) return () => { if (pollRef.current) clearInterval(pollRef.current) } }, [checkHealth, refreshMetrics]) return { connected, metrics, stats, memorySamples, loading, sendMessage, teachModel, learnText, dream, reason, refreshMetrics, checkHealth, } }