palimpseste-max / web /src /hooks /useApi.ts
thefinalboss's picture
Upload web/src/hooks/useApi.ts with huggingface_hub
14f675c verified
Raw
History Blame Contribute Delete
3.88 kB
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<T>(url: string, options?: RequestInit): Promise<T> {
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<Metrics | null>(null)
const [stats, setStats] = useState<Stats | null>(null)
const [memorySamples, setMemorySamples] = useState<MemorySamples | null>(null)
const [loading, setLoading] = useState(false)
const pollRef = useRef<number | null>(null)
const checkHealth = useCallback(async () => {
try {
await fetchJson('/health')
setConnected(true)
} catch {
setConnected(false)
}
}, [])
const refreshMetrics = useCallback(async () => {
try {
const m = await fetchJson<Metrics>('/metrics')
setMetrics(m)
const s = await fetchJson<Stats>('/stats')
setStats(s)
const ms = await fetchJson<MemorySamples>('/memory/samples?limit=100')
setMemorySamples(ms)
setConnected(true)
} catch {
setConnected(false)
}
}, [])
const sendMessage = useCallback(async (
message: string, temperature?: number, maxTokens?: number
): Promise<ChatResponse> => {
setLoading(true)
try {
const resp = await fetchJson<ChatResponse>('/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<TeachResponse> => {
setLoading(true)
try {
const resp = await fetchJson<TeachResponse>('/teach', {
method: 'POST',
body: JSON.stringify({ question, answer }),
})
refreshMetrics()
return resp
} finally {
setLoading(false)
}
}, [refreshMetrics])
const learnText = useCallback(async (text: string): Promise<any> => {
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<any> => {
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<any> => {
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,
}
}