diff --git a/frontend/src/pages/Agents.tsx b/frontend/src/pages/Agents.tsx
index 00647471..eb9dbab2 100644
--- a/frontend/src/pages/Agents.tsx
+++ b/frontend/src/pages/Agents.tsx
@@ -9,7 +9,10 @@ import {
CpuChipIcon,
ServerIcon,
BoltIcon,
- ExclamationTriangleIcon
+ ExclamationTriangleIcon,
+ CommandLineIcon,
+ CloudIcon,
+ ChevronDownIcon
} from '@heroicons/react/24/outline';
import { agentApi } from '../services/api';
@@ -19,10 +22,21 @@ interface Agent {
endpoint: string;
model: string;
specialty: string;
- status: 'online' | 'offline' | 'busy' | 'idle';
+ status: 'online' | 'offline' | 'busy' | 'idle' | 'available';
max_concurrent: number;
current_tasks: number;
last_seen: string;
+ agent_type?: 'ollama' | 'cli';
+ cli_config?: {
+ host?: string;
+ node_version?: string;
+ model?: string;
+ specialization?: string;
+ max_concurrent?: number;
+ command_timeout?: number;
+ ssh_timeout?: number;
+ agent_type?: string;
+ };
capabilities?: string[];
metrics?: {
tasks_completed: number;
@@ -33,6 +47,8 @@ interface Agent {
export default function Agents() {
const [showRegistrationForm, setShowRegistrationForm] = useState(false);
+ const [showCliRegistrationForm, setShowCliRegistrationForm] = useState(false);
+ const [registrationMode, setRegistrationMode] = useState<'ollama' | 'cli'>('ollama');
const [newAgent, setNewAgent] = useState({
name: '',
endpoint: '',
@@ -40,6 +56,17 @@ export default function Agents() {
specialty: 'general',
max_concurrent: 1
});
+ const [newCliAgent, setNewCliAgent] = useState({
+ id: '',
+ host: '',
+ node_version: '',
+ model: 'gemini-2.5-pro',
+ specialization: 'general_ai',
+ max_concurrent: 2,
+ command_timeout: 60,
+ ssh_timeout: 5,
+ agent_type: 'gemini'
+ });
const { data: agents = [], isLoading, refetch } = useQuery({
queryKey: ['agents'],
@@ -47,15 +74,16 @@ export default function Agents() {
try {
return await agentApi.getAgents();
} catch (err) {
- // Return mock data if API fails
+ // Return mock data if API fails - mixed agent types
return [
{
- id: 'walnut',
+ id: 'walnut-ollama',
name: 'WALNUT',
endpoint: 'http://192.168.1.27:11434',
model: 'deepseek-coder-v2:latest',
specialty: 'frontend',
status: 'online',
+ agent_type: 'ollama',
max_concurrent: 2,
current_tasks: 1,
last_seen: new Date().toISOString(),
@@ -67,12 +95,13 @@ export default function Agents() {
}
},
{
- id: 'ironwood',
+ id: 'ironwood-ollama',
name: 'IRONWOOD',
endpoint: 'http://192.168.1.113:11434',
model: 'qwen2.5-coder:latest',
specialty: 'backend',
status: 'online',
+ agent_type: 'ollama',
max_concurrent: 2,
current_tasks: 0,
last_seen: new Date().toISOString(),
@@ -90,6 +119,7 @@ export default function Agents() {
model: 'qwen2.5:latest',
specialty: 'documentation',
status: 'offline',
+ agent_type: 'ollama',
max_concurrent: 1,
current_tasks: 0,
last_seen: new Date(Date.now() - 3600000).toISOString(),
@@ -99,6 +129,59 @@ export default function Agents() {
uptime: '0h 0m',
response_time: 0
}
+ },
+ // CLI Agents
+ {
+ id: 'walnut-gemini',
+ name: 'WALNUT-GEMINI',
+ endpoint: 'cli://walnut',
+ model: 'gemini-2.5-pro',
+ specialty: 'general_ai',
+ status: 'available',
+ agent_type: 'cli',
+ max_concurrent: 2,
+ current_tasks: 0,
+ last_seen: new Date().toISOString(),
+ cli_config: {
+ host: 'walnut',
+ node_version: 'v22.14.0',
+ model: 'gemini-2.5-pro',
+ specialization: 'general_ai',
+ command_timeout: 60,
+ ssh_timeout: 5
+ },
+ capabilities: ['Advanced Reasoning', 'General AI', 'Multi-modal'],
+ metrics: {
+ tasks_completed: 12,
+ uptime: '4h 23m',
+ response_time: 3.1
+ }
+ },
+ {
+ id: 'ironwood-gemini',
+ name: 'IRONWOOD-GEMINI',
+ endpoint: 'cli://ironwood',
+ model: 'gemini-2.5-pro',
+ specialty: 'reasoning',
+ status: 'available',
+ agent_type: 'cli',
+ max_concurrent: 2,
+ current_tasks: 1,
+ last_seen: new Date().toISOString(),
+ cli_config: {
+ host: 'ironwood',
+ node_version: 'v22.17.0',
+ model: 'gemini-2.5-pro',
+ specialization: 'reasoning',
+ command_timeout: 60,
+ ssh_timeout: 5
+ },
+ capabilities: ['Complex Reasoning', 'Problem Solving', 'Analysis'],
+ metrics: {
+ tasks_completed: 8,
+ uptime: '2h 15m',
+ response_time: 2.7
+ }
}
] as Agent[];
}
@@ -118,9 +201,41 @@ export default function Agents() {
}
};
+ const handleRegisterCliAgent = async (e: React.FormEvent) => {
+ e.preventDefault();
+ try {
+ await agentApi.registerCliAgent(newCliAgent);
+ setNewCliAgent({
+ id: '',
+ host: '',
+ node_version: '',
+ model: 'gemini-2.5-pro',
+ specialization: 'general_ai',
+ max_concurrent: 2,
+ command_timeout: 60,
+ ssh_timeout: 5,
+ agent_type: 'gemini'
+ });
+ setShowCliRegistrationForm(false);
+ refetch();
+ } catch (err) {
+ console.error('Failed to register CLI agent:', err);
+ }
+ };
+
+ const handleRegisterPredefinedAgents = async () => {
+ try {
+ await agentApi.registerPredefinedCliAgents();
+ refetch();
+ } catch (err) {
+ console.error('Failed to register predefined CLI agents:', err);
+ }
+ };
+
const getStatusIcon = (status: string) => {
switch (status) {
case 'online':
+ case 'available':
return
Manage AI agents in your distributed cluster
- +{ollamaAgents}
+Ollama Agents
+{cliAgents}
+CLI Agents
+{onlineAgents}
-Online
+Available
{busyAgents}
-Busy
-{totalTasks}
Tasks Completed
@@ -237,10 +398,18 @@ export default function Agents() { {/* Agent Header */}{agent.specialty}
+ {agent.cli_config?.host && ( +SSH: {agent.cli_config.host} (Node {agent.cli_config.node_version})
+ )}