| |
| |
| |
| |
| |
| |
| import { useMemo, useState } from 'react'; |
| import { useAgenticCatalog } from '../../agentic/useAgenticCatalog'; |
| import { deriveStatus } from './ToolStatusBadge'; |
| export function useToolsInventory({ backendUrl, apiKey }) { |
| const { catalog, loading, error, refresh } = useAgenticCatalog({ |
| backendUrl, |
| apiKey, |
| enabled: true, |
| }); |
| const [search, setSearch] = useState(''); |
| const [statusFilter, setStatusFilter] = useState('all'); |
| const [typeFilter, setTypeFilter] = useState('all'); |
| |
| const allItems = useMemo(() => { |
| const toolItems = (catalog?.tools || []) |
| .filter((t) => t.id && t.name) |
| .map((t) => ({ kind: 'tool', data: t })); |
| const a2aItems = (catalog?.a2a_agents || []) |
| .filter((a) => a.id && a.name) |
| .map((a) => ({ kind: 'a2a_agent', data: a })); |
| return [...toolItems, ...a2aItems]; |
| }, [catalog?.tools, catalog?.a2a_agents]); |
| |
| const items = useMemo(() => { |
| let filtered = allItems; |
| |
| if (typeFilter !== 'all') { |
| const kind = typeFilter === 'a2a' ? 'a2a_agent' : 'tool'; |
| filtered = filtered.filter((item) => item.kind === kind); |
| } |
| |
| if (search.trim()) { |
| const q = search.toLowerCase(); |
| filtered = filtered.filter((item) => { |
| const d = item.data; |
| const searchable = `${d.name} ${d.description || ''} ${d.id} ${item.kind === 'a2a_agent' && 'endpoint_url' in d ? d.endpoint_url || '' : ''}`; |
| return searchable.toLowerCase().includes(q); |
| }); |
| } |
| |
| if (statusFilter !== 'all') { |
| filtered = filtered.filter((item) => deriveStatus(item.data.enabled) === statusFilter); |
| } |
| return filtered; |
| }, [allItems, search, statusFilter, typeFilter]); |
| |
| const counts = useMemo(() => { |
| const tools = (catalog?.tools || []); |
| const a2a = (catalog?.a2a_agents || []); |
| return { |
| total: tools.length + a2a.length, |
| tools: { |
| total: tools.length, |
| active: tools.filter((t) => t.enabled === true).length, |
| inactive: tools.filter((t) => t.enabled === false).length, |
| }, |
| a2a: { |
| total: a2a.length, |
| active: a2a.filter((a) => a.enabled === true).length, |
| inactive: a2a.filter((a) => a.enabled === false).length, |
| }, |
| active: tools.filter((t) => t.enabled === true).length + a2a.filter((a) => a.enabled === true).length, |
| inactive: tools.filter((t) => t.enabled === false).length + a2a.filter((a) => a.enabled === false).length, |
| }; |
| }, [catalog?.tools, catalog?.a2a_agents]); |
| return { |
| items, |
| counts, |
| loading, |
| error, |
| refresh, |
| search, |
| setSearch, |
| statusFilter, |
| setStatusFilter, |
| typeFilter, |
| setTypeFilter, |
| forgeHealthy: catalog?.forge?.healthy ?? null, |
| }; |
| } |
|
|