File size: 3,413 Bytes
921d377
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
/**
 * Hook that wraps useAgenticCatalog and provides a unified capabilities view.
 *
 * Merges catalog.tools + catalog.a2a_agents into a single CapabilityItem[]
 * list with search, status, and type filtering.
 */
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');
    /* Build unified list from both sources */
    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]);
    /* Filtered list */
    const items = useMemo(() => {
        let filtered = allItems;
        // Type filter
        if (typeFilter !== 'all') {
            const kind = typeFilter === 'a2a' ? 'a2a_agent' : 'tool';
            filtered = filtered.filter((item) => item.kind === kind);
        }
        // Search filter
        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);
            });
        }
        // Status filter
        if (statusFilter !== 'all') {
            filtered = filtered.filter((item) => deriveStatus(item.data.enabled) === statusFilter);
        }
        return filtered;
    }, [allItems, search, statusFilter, typeFilter]);
    /* Counts */
    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,
    };
}