Spaces:
Running
Running
Upload components/AgentGrid.js with huggingface_hub
Browse files- components/AgentGrid.js +118 -0
components/AgentGrid.js
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { useState } from 'react';
|
| 2 |
+
|
| 3 |
+
const colorMap = {
|
| 4 |
+
blue: { bg: 'bg-blue-500/10', border: 'border-blue-500/30', text: 'text-blue-400', glow: 'shadow-blue-500/20' },
|
| 5 |
+
purple: { bg: 'bg-purple-500/10', border: 'border-purple-500/30', text: 'text-purple-400', glow: 'shadow-purple-500/20' },
|
| 6 |
+
indigo: { bg: 'bg-indigo-500/10', border: 'border-indigo-500/30', text: 'text-indigo-400', glow: 'shadow-indigo-500/20' },
|
| 7 |
+
green: { bg: 'bg-green-500/10', border: 'border-green-500/30', text: 'text-green-400', glow: 'shadow-green-500/20' },
|
| 8 |
+
pink: { bg: 'bg-pink-500/10', border: 'border-pink-500/30', text: 'text-pink-400', glow: 'shadow-pink-500/20' },
|
| 9 |
+
orange: { bg: 'bg-orange-500/10', border: 'border-orange-500/30', text: 'text-orange-400', glow: 'shadow-orange-500/20' },
|
| 10 |
+
yellow: { bg: 'bg-yellow-500/10', border: 'border-yellow-500/30', text: 'text-yellow-400', glow: 'shadow-yellow-500/20' },
|
| 11 |
+
cyan: { bg: 'bg-cyan-500/10', border: 'border-cyan-500/30', text: 'text-cyan-400', glow: 'shadow-cyan-500/20' },
|
| 12 |
+
red: { bg: 'bg-red-500/10', border: 'border-red-500/30', text: 'text-red-400', glow: 'shadow-red-500/20' },
|
| 13 |
+
teal: { bg: 'bg-teal-500/10', border: 'border-teal-500/30', text: 'text-teal-400', glow: 'shadow-teal-500/20' },
|
| 14 |
+
violet: { bg: 'bg-violet-500/10', border: 'border-violet-500/30', text: 'text-violet-400', glow: 'shadow-violet-500/20' },
|
| 15 |
+
};
|
| 16 |
+
|
| 17 |
+
const statusConfig = {
|
| 18 |
+
idle: { label: 'Idle', dot: 'bg-gray-600', bg: 'bg-gray-500/5' },
|
| 19 |
+
active: { label: 'Active', dot: 'bg-yellow-500 animate-pulse', bg: '' },
|
| 20 |
+
done: { label: 'Done', dot: 'bg-green-500', bg: '' },
|
| 21 |
+
failed: { label: 'Failed', dot: 'bg-red-500', bg: '' },
|
| 22 |
+
};
|
| 23 |
+
|
| 24 |
+
export default function AgentGrid({ agents, statuses, currentPhase }) {
|
| 25 |
+
const [selectedAgent, setSelectedAgent] = useState(null);
|
| 26 |
+
|
| 27 |
+
const phaseNames = ['Planning', 'Execution', 'Validation', 'Documentation', 'Learning'];
|
| 28 |
+
|
| 29 |
+
return (
|
| 30 |
+
<div className="space-y-6">
|
| 31 |
+
{/* Phase Indicator */}
|
| 32 |
+
{currentPhase >= 0 && (
|
| 33 |
+
<div className="glass-card p-4 animate-slide-up">
|
| 34 |
+
<div className="flex items-center gap-3 mb-3">
|
| 35 |
+
<div className="w-2 h-2 rounded-full bg-indigo-500 animate-pulse" />
|
| 36 |
+
<span className="text-sm font-medium text-indigo-400">
|
| 37 |
+
Current Phase: {phaseNames[currentPhase] || 'Unknown'}
|
| 38 |
+
</span>
|
| 39 |
+
</div>
|
| 40 |
+
<div className="flex gap-2">
|
| 41 |
+
{phaseNames.map((name, i) => (
|
| 42 |
+
<div
|
| 43 |
+
key={name}
|
| 44 |
+
className={`flex-1 h-1.5 rounded-full transition-all duration-500 ${
|
| 45 |
+
i < currentPhase ? 'bg-green-500' :
|
| 46 |
+
i === currentPhase ? 'bg-indigo-500 animate-pulse' :
|
| 47 |
+
'bg-gray-800'
|
| 48 |
+
}`}
|
| 49 |
+
/>
|
| 50 |
+
))}
|
| 51 |
+
</div>
|
| 52 |
+
</div>
|
| 53 |
+
)}
|
| 54 |
+
|
| 55 |
+
{/* Agent Grid */}
|
| 56 |
+
<div className="grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-3 gap-4">
|
| 57 |
+
{agents.map((agent, index) => {
|
| 58 |
+
const colors = colorMap[agent.color];
|
| 59 |
+
const status = statuses[agent.id] || 'idle';
|
| 60 |
+
const statusInfo = statusConfig[status];
|
| 61 |
+
const isSelected = selectedAgent === agent.id;
|
| 62 |
+
|
| 63 |
+
return (
|
| 64 |
+
<div
|
| 65 |
+
key={agent.id}
|
| 66 |
+
onClick={() => setSelectedAgent(isSelected ? null : agent.id)}
|
| 67 |
+
className={`agent-card cursor-pointer animate-slide-up ${
|
| 68 |
+
status === 'active' ? `${colors.bg} ${colors.border} shadow-lg ${colors.glow}` :
|
| 69 |
+
status === 'done' ? 'border-green-500/20' :
|
| 70 |
+
''
|
| 71 |
+
}`}
|
| 72 |
+
style={{ animationDelay: `${index * 50}ms` }}
|
| 73 |
+
>
|
| 74 |
+
<div className="flex items-start gap-3">
|
| 75 |
+
<div className={`w-10 h-10 rounded-xl ${colors.bg} flex items-center justify-center text-lg flex-shrink-0`}>
|
| 76 |
+
{agent.icon}
|
| 77 |
+
</div>
|
| 78 |
+
<div className="flex-1 min-w-0">
|
| 79 |
+
<div className="flex items-center justify-between gap-2">
|
| 80 |
+
<h3 className={`text-sm font-semibold ${colors.text} truncate`}>{agent.name}</h3>
|
| 81 |
+
<div className="flex items-center gap-1.5 flex-shrink-0">
|
| 82 |
+
<div className={`status-dot ${statusInfo.dot}`} />
|
| 83 |
+
<span className="text-xs text-gray-500">{statusInfo.label}</span>
|
| 84 |
+
</div>
|
| 85 |
+
</div>
|
| 86 |
+
<p className="text-xs text-gray-500 mt-1 line-clamp-2">{agent.description}</p>
|
| 87 |
+
</div>
|
| 88 |
+
</div>
|
| 89 |
+
|
| 90 |
+
{isSelected && (
|
| 91 |
+
<div className="mt-3 pt-3 border-t border-gray-800/50 animate-slide-up">
|
| 92 |
+
<div className="space-y-2">
|
| 93 |
+
<div className="flex items-center gap-2">
|
| 94 |
+
<span className="text-xs text-gray-500">Agent ID:</span>
|
| 95 |
+
<code className="text-xs text-gray-300 bg-gray-800/50 px-1.5 py-0.5 rounded">{agent.id}</code>
|
| 96 |
+
</div>
|
| 97 |
+
<div className="flex items-center gap-2">
|
| 98 |
+
<span className="text-xs text-gray-500">Status:</span>
|
| 99 |
+
<span className={`text-xs font-medium ${status === 'done' ? 'text-green-400' : status === 'active' ? 'text-yellow-400' : 'text-gray-400'}`}>
|
| 100 |
+
{status.toUpperCase()}
|
| 101 |
+
</span>
|
| 102 |
+
</div>
|
| 103 |
+
<div className="flex items-center gap-2">
|
| 104 |
+
<span className="text-xs text-gray-500">Phase:</span>
|
| 105 |
+
<span className="text-xs text-gray-300">
|
| 106 |
+
{currentPhase >= 0 ? phaseNames[currentPhase] : 'Waiting'}
|
| 107 |
+
</span>
|
| 108 |
+
</div>
|
| 109 |
+
</div>
|
| 110 |
+
</div>
|
| 111 |
+
)}
|
| 112 |
+
</div>
|
| 113 |
+
);
|
| 114 |
+
})}
|
| 115 |
+
</div>
|
| 116 |
+
</div>
|
| 117 |
+
);
|
| 118 |
+
}
|