jan/web-app/src/hooks/useProviderModels.ts
2025-08-23 15:07:42 +02:00

89 lines
2.5 KiB
TypeScript

import { useState, useEffect, useCallback, useRef } from 'react'
import { fetchModelsFromProvider } from '@/services/providers'
type UseProviderModelsState = {
models: string[]
loading: boolean
error: string | null
refetch: () => void
}
const modelsCache = new Map<string, { models: string[]; timestamp: number }>()
const CACHE_DURATION = 5 * 60 * 1000 // 5 minutes
export const useProviderModels = (provider?: ModelProvider): UseProviderModelsState => {
const [models, setModels] = useState<string[]>([])
const [loading, setLoading] = useState(false)
const [error, setError] = useState<string | null>(null)
const prevProviderKey = useRef<string>('')
const fetchModels = useCallback(async () => {
if (!provider || !provider.base_url) {
// Clear models if provider is invalid (base_url is required, api_key is optional)
setModels([])
setError(null)
setLoading(false)
return
}
// Clear any previous state when starting a new fetch for a different provider
const currentProviderKey = `${provider.provider}-${provider.base_url}`
if (currentProviderKey !== prevProviderKey.current) {
setModels([])
setError(null)
setLoading(false)
prevProviderKey.current = currentProviderKey
}
const cacheKey = `${provider.provider}-${provider.base_url}`
const cached = modelsCache.get(cacheKey)
// Check cache first
if (cached && Date.now() - cached.timestamp < CACHE_DURATION) {
setModels(cached.models)
return
}
setLoading(true)
setError(null)
try {
const fetchedModels = await fetchModelsFromProvider(provider)
const sortedModels = fetchedModels.sort((a, b) => a.localeCompare(b))
setModels(sortedModels)
// Cache the results
modelsCache.set(cacheKey, {
models: sortedModels,
timestamp: Date.now(),
})
} catch (err) {
const errorMessage = err instanceof Error ? err.message : 'Failed to fetch models'
setError(errorMessage)
console.error(`Error fetching models from ${provider.provider}:`, err)
} finally {
setLoading(false)
}
}, [provider])
const refetch = useCallback(() => {
if (provider) {
const cacheKey = `${provider.provider}-${provider.base_url}`
modelsCache.delete(cacheKey)
fetchModels()
}
}, [provider, fetchModels])
useEffect(() => {
fetchModels()
}, [fetchModels])
return {
models,
loading,
error,
refetch,
}
}