import React, { useState, useCallback } from 'react';
import { useApi } from '../hooks/useApi';
import { getMeshAgents, registerMeshAgent, unregisterMeshAgent, type MeshAgent } from '../api/discovery';
export default function CapabilityRegistry() {
const [showForm, setShowForm] = useState(false);
const agentsQuery = useApi(() => getMeshAgents(), []);
const agents = agentsQuery.data ?? [];
const handleUnregister = useCallback(async (name: string) => {
if (!confirm(`Unregister agent "${name}"?`)) return;
await unregisterMeshAgent(name);
agentsQuery.refetch();
}, [agentsQuery]);
const handleRegister = useCallback(async (data: { name: string; description: string; capabilities: string[]; endpoint: string }) => {
await registerMeshAgent(data);
setShowForm(false);
agentsQuery.refetch();
}, [agentsQuery]);
return (
🤖 Agent Registry
{showForm &&
setShowForm(false)} />}
{agentsQuery.loading && Loading...
}
{agentsQuery.error && Error: {agentsQuery.error}
}
{!agentsQuery.loading && agents.length === 0 && (
No agents registered yet.
)}
{agents.map((agent) => (
{agent.name}
{agent.description}
{agent.capabilities.map((cap) => (
{cap}
))}
Endpoint: {agent.endpoint}
Protocol: {agent.protocol}
Last seen: {new Date(agent.last_seen).toLocaleString()}
))}
);
}
function RegisterForm({ onSubmit, onCancel }: {
onSubmit: (data: { name: string; description: string; capabilities: string[]; endpoint: string }) => void;
onCancel: () => void;
}) {
const [name, setName] = useState('');
const [description, setDescription] = useState('');
const [capabilities, setCapabilities] = useState('');
const [endpoint, setEndpoint] = useState('');
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
onSubmit({
name,
description,
capabilities: capabilities.split(',').map(s => s.trim()).filter(Boolean),
endpoint,
});
};
return (
);
}
const cardStyle: React.CSSProperties = {
padding: '16px', border: '1px solid #e2e8f0', borderRadius: '8px', marginBottom: '12px',
};
const btnStyle: React.CSSProperties = {
padding: '8px 16px', background: '#3b82f6', color: 'white', border: 'none',
borderRadius: '6px', cursor: 'pointer', fontSize: '14px',
};
const smallBtnStyle: React.CSSProperties = {
padding: '4px 10px', background: 'transparent', border: '1px solid #d1d5db',
borderRadius: '4px', cursor: 'pointer', fontSize: '13px',
};
const dangerBtnStyle: React.CSSProperties = {
padding: '4px 10px', background: 'transparent', border: '1px solid #fca5a5', color: '#dc2626',
borderRadius: '4px', cursor: 'pointer', fontSize: '13px',
};
const tagStyle: React.CSSProperties = {
padding: '2px 8px', background: '#e0f2fe', color: '#0369a1', borderRadius: '12px',
fontSize: '12px', fontWeight: 500,
};
const inputStyle: React.CSSProperties = {
width: '100%', padding: '6px 10px', border: '1px solid #d1d5db', borderRadius: '4px',
fontSize: '14px', marginTop: '4px',
};