Last active
December 9, 2025 12:14
-
-
Save paulweezydesign/36733b8c1968e3c0c4fcbc46776fb1f6 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 'use client' | |
| import { LucideIcon } from 'lucide-react' | |
| interface AgentCardProps { | |
| agent: { | |
| id: string | |
| name: string | |
| description: string | |
| icon: LucideIcon | |
| color: string | |
| } | |
| isSelected: boolean | |
| onClick: () => void | |
| } | |
| export default function AgentCard({ agent, isSelected, onClick }: AgentCardProps) { | |
| const Icon = agent.icon | |
| return ( | |
| <div | |
| onClick={onClick} | |
| className={` | |
| agent-card-hover | |
| cursor-pointer | |
| bg-white dark:bg-gray-800 | |
| rounded-xl | |
| shadow-md | |
| p-6 | |
| border-2 | |
| transition-all | |
| ${ | |
| isSelected | |
| ? 'border-purple-500 ring-4 ring-purple-200 dark:ring-purple-900' | |
| : 'border-transparent hover:border-gray-300 dark:hover:border-gray-600' | |
| } | |
| `} | |
| > | |
| <div className="flex items-start gap-4"> | |
| <div className={`${agent.color} p-3 rounded-lg text-white`}> | |
| <Icon className="w-6 h-6" /> | |
| </div> | |
| <div className="flex-1"> | |
| <h3 className="text-xl font-bold text-gray-900 dark:text-white mb-2"> | |
| {agent.name} | |
| </h3> | |
| <p className="text-gray-600 dark:text-gray-300 text-sm"> | |
| {agent.description} | |
| </p> | |
| </div> | |
| </div> | |
| {isSelected && ( | |
| <div className="mt-4 pt-4 border-t border-gray-200 dark:border-gray-700"> | |
| <div className="flex items-center gap-2 text-sm text-purple-600 dark:text-purple-400"> | |
| <div className="w-2 h-2 bg-purple-500 rounded-full animate-pulse"></div> | |
| <span className="font-medium">Active Agent</span> | |
| </div> | |
| </div> | |
| )} | |
| </div> | |
| ) | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { NextRequest, NextResponse } from 'next/server' | |
| import { getAgentById } from '@/lib/mastra' | |
| export async function POST(request: NextRequest) { | |
| try { | |
| const body = await request.json() | |
| const { agentId, message, conversationHistory = [] } = body | |
| if (!agentId || !message) { | |
| return NextResponse.json( | |
| { error: 'Missing required fields: agentId and message' }, | |
| { status: 400 } | |
| ) | |
| } | |
| const agent = getAgentById(agentId) | |
| if (!agent) { | |
| return NextResponse.json( | |
| { error: `Agent not found: ${agentId}` }, | |
| { status: 404 } | |
| ) | |
| } | |
| // Build messages array with conversation history | |
| const messages = [ | |
| ...conversationHistory.map((msg: any) => ({ | |
| role: msg.role, | |
| content: msg.content, | |
| })), | |
| { | |
| role: 'user', | |
| content: message, | |
| }, | |
| ] | |
| // Generate response using the agent | |
| const response = await agent.generate(messages) | |
| return NextResponse.json({ | |
| success: true, | |
| response: response.text, | |
| agentId, | |
| timestamp: new Date().toISOString(), | |
| }) | |
| } catch (error) { | |
| console.error('Agent API Error:', error) | |
| return NextResponse.json( | |
| { | |
| error: 'Failed to process request', | |
| details: error instanceof Error ? error.message : 'Unknown error' | |
| }, | |
| { status: 500 } | |
| ) | |
| } | |
| } | |
| export async function GET() { | |
| return NextResponse.json({ | |
| message: 'Mastra Multi-Agent System API', | |
| version: '1.0.0', | |
| agents: [ | |
| 'project-manager', | |
| 'research-agent', | |
| 'design-agent', | |
| 'frontend-agent', | |
| 'backend-agent', | |
| 'qa-agent', | |
| ], | |
| }) | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 'use client' | |
| import { useState, useRef, useEffect } from 'react' | |
| import { Send, X, Loader2, User, Bot } from 'lucide-react' | |
| interface Message { | |
| role: 'user' | 'assistant' | |
| content: string | |
| timestamp: string | |
| } | |
| interface ChatInterfaceProps { | |
| agentId: string | |
| agentName: string | |
| onClose: () => void | |
| } | |
| export default function ChatInterface({ agentId, agentName, onClose }: ChatInterfaceProps) { | |
| const [messages, setMessages] = useState<Message[]>([]) | |
| const [input, setInput] = useState('') | |
| const [isLoading, setIsLoading] = useState(false) | |
| const messagesEndRef = useRef<HTMLDivElement>(null) | |
| const scrollToBottom = () => { | |
| messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' }) | |
| } | |
| useEffect(() => { | |
| scrollToBottom() | |
| }, [messages]) | |
| useEffect(() => { | |
| // Add welcome message when agent is selected | |
| setMessages([{ | |
| role: 'assistant', | |
| content: `Hello! I'm the ${agentName}. How can I assist you today?`, | |
| timestamp: new Date().toISOString(), | |
| }]) | |
| }, [agentId, agentName]) | |
| const handleSubmit = async (e: React.FormEvent) => { | |
| e.preventDefault() | |
| if (!input.trim() || isLoading) return | |
| const userMessage: Message = { | |
| role: 'user', | |
| content: input.trim(), | |
| timestamp: new Date().toISOString(), | |
| } | |
| setMessages(prev => [...prev, userMessage]) | |
| setInput('') | |
| setIsLoading(true) | |
| try { | |
| const response = await fetch('/api/agents', { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| }, | |
| body: JSON.stringify({ | |
| agentId, | |
| message: userMessage.content, | |
| conversationHistory: messages, | |
| }), | |
| }) | |
| const data = await response.json() | |
| if (data.success) { | |
| const assistantMessage: Message = { | |
| role: 'assistant', | |
| content: data.response, | |
| timestamp: data.timestamp, | |
| } | |
| setMessages(prev => [...prev, assistantMessage]) | |
| } else { | |
| throw new Error(data.error || 'Failed to get response') | |
| } | |
| } catch (error) { | |
| console.error('Chat error:', error) | |
| const errorMessage: Message = { | |
| role: 'assistant', | |
| content: `Sorry, I encountered an error. Please make sure you have set your OPENAI_API_KEY environment variable. Error: ${error instanceof Error ? error.message : 'Unknown error'}`, | |
| timestamp: new Date().toISOString(), | |
| } | |
| setMessages(prev => [...prev, errorMessage]) | |
| } finally { | |
| setIsLoading(false) | |
| } | |
| } | |
| return ( | |
| <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center p-4 z-50"> | |
| <div className="bg-white dark:bg-gray-800 rounded-2xl shadow-2xl w-full max-w-4xl h-[80vh] flex flex-col"> | |
| {/* Header */} | |
| <div className="gradient-bg text-white p-6 rounded-t-2xl flex items-center justify-between"> | |
| <div> | |
| <h2 className="text-2xl font-bold">{agentName}</h2> | |
| <p className="text-gray-100 text-sm mt-1">AI Assistant</p> | |
| </div> | |
| <button | |
| onClick={onClose} | |
| className="p-2 hover:bg-white hover:bg-opacity-20 rounded-lg transition-colors" | |
| > | |
| <X className="w-6 h-6" /> | |
| </button> | |
| </div> | |
| {/* Messages */} | |
| <div className="flex-1 overflow-y-auto p-6 space-y-4"> | |
| {messages.map((message, index) => ( | |
| <div | |
| key={index} | |
| className={`chat-message flex gap-3 ${ | |
| message.role === 'user' ? 'flex-row-reverse' : 'flex-row' | |
| }`} | |
| > | |
| <div | |
| className={`flex-shrink-0 w-8 h-8 rounded-full flex items-center justify-center ${ | |
| message.role === 'user' | |
| ? 'bg-purple-500 text-white' | |
| : 'bg-gray-300 dark:bg-gray-600 text-gray-700 dark:text-gray-200' | |
| }`} | |
| > | |
| {message.role === 'user' ? <User className="w-4 h-4" /> : <Bot className="w-4 h-4" />} | |
| </div> | |
| <div | |
| className={`flex-1 max-w-[80%] ${ | |
| message.role === 'user' ? 'text-right' : 'text-left' | |
| }`} | |
| > | |
| <div | |
| className={`inline-block p-4 rounded-2xl ${ | |
| message.role === 'user' | |
| ? 'bg-purple-500 text-white' | |
| : 'bg-gray-100 dark:bg-gray-700 text-gray-900 dark:text-white' | |
| }`} | |
| > | |
| <p className="whitespace-pre-wrap break-words">{message.content}</p> | |
| </div> | |
| <p className="text-xs text-gray-500 dark:text-gray-400 mt-1 px-2"> | |
| {new Date(message.timestamp).toLocaleTimeString()} | |
| </p> | |
| </div> | |
| </div> | |
| ))} | |
| {isLoading && ( | |
| <div className="flex gap-3"> | |
| <div className="flex-shrink-0 w-8 h-8 rounded-full bg-gray-300 dark:bg-gray-600 flex items-center justify-center"> | |
| <Bot className="w-4 h-4 text-gray-700 dark:text-gray-200" /> | |
| </div> | |
| <div className="bg-gray-100 dark:bg-gray-700 p-4 rounded-2xl"> | |
| <Loader2 className="w-5 h-5 animate-spin text-gray-600 dark:text-gray-300" /> | |
| </div> | |
| </div> | |
| )} | |
| <div ref={messagesEndRef} /> | |
| </div> | |
| {/* Input */} | |
| <form onSubmit={handleSubmit} className="p-6 border-t border-gray-200 dark:border-gray-700"> | |
| <div className="flex gap-3"> | |
| <input | |
| type="text" | |
| value={input} | |
| onChange={(e) => setInput(e.target.value)} | |
| placeholder="Type your message..." | |
| disabled={isLoading} | |
| className="flex-1 px-4 py-3 bg-gray-100 dark:bg-gray-700 text-gray-900 dark:text-white rounded-lg focus:outline-none focus:ring-2 focus:ring-purple-500 disabled:opacity-50" | |
| /> | |
| <button | |
| type="submit" | |
| disabled={isLoading || !input.trim()} | |
| className="px-6 py-3 bg-purple-500 text-white rounded-lg hover:bg-purple-600 disabled:opacity-50 disabled:cursor-not-allowed transition-colors flex items-center gap-2" | |
| > | |
| {isLoading ? ( | |
| <Loader2 className="w-5 h-5 animate-spin" /> | |
| ) : ( | |
| <> | |
| <Send className="w-5 h-5" /> | |
| <span>Send</span> | |
| </> | |
| )} | |
| </button> | |
| </div> | |
| </form> | |
| </div> | |
| </div> | |
| ) | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| @import "tailwindcss"; | |
| :root { | |
| --background: #ffffff; | |
| --foreground: #171717; | |
| } | |
| @media (prefers-color-scheme: dark) { | |
| :root { | |
| --background: #0a0a0a; | |
| --foreground: #ededed; | |
| } | |
| } | |
| body { | |
| color: var(--foreground); | |
| background: var(--background); | |
| font-family: Arial, Helvetica, sans-serif; | |
| } | |
| @layer utilities { | |
| .text-balance { | |
| text-wrap: balance; | |
| } | |
| } | |
| .gradient-bg { | |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | |
| } | |
| .agent-card-hover { | |
| transition: all 0.3s ease; | |
| } | |
| .agent-card-hover:hover { | |
| transform: translateY(-4px); | |
| box-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1); | |
| } | |
| .chat-message { | |
| animation: slideIn 0.3s ease-out; | |
| } | |
| @keyframes slideIn { | |
| from { | |
| opacity: 0; | |
| transform: translateY(10px); | |
| } | |
| to { | |
| opacity: 1; | |
| transform: translateY(0); | |
| } | |
| } | |
| .workflow-node { | |
| animation: fadeIn 0.5s ease-out; | |
| } | |
| @keyframes fadeIn { | |
| from { | |
| opacity: 0; | |
| } | |
| to { | |
| opacity: 1; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import type { Metadata } from 'next' | |
| import { Inter } from 'next/font/google' | |
| import './globals.css' | |
| const inter = Inter({ subsets: ['latin'] }) | |
| export const metadata: Metadata = { | |
| title: 'Mastra Multi-Agent System', | |
| description: 'A comprehensive multi-agent system for software development using Mastra.ai', | |
| } | |
| export default function RootLayout({ | |
| children, | |
| }: { | |
| children: React.ReactNode | |
| }) { | |
| return ( | |
| <html lang="en"> | |
| <body className={inter.className}>{children}</body> | |
| </html> | |
| ) | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 'use client' | |
| import { useState } from 'react' | |
| import AgentCard from '@/components/agent-card' | |
| import ChatInterface from '@/components/chat-interface' | |
| import WorkflowVisualizer from '@/components/workflow-visualizer' | |
| import { | |
| Briefcase, | |
| Search, | |
| Palette, | |
| Code, | |
| Server, | |
| Bug, | |
| Workflow | |
| } from 'lucide-react' | |
| const agents = [ | |
| { | |
| id: 'project-manager', | |
| name: 'Project Manager', | |
| description: 'Coordinates tasks, manages timeline, and orchestrates other agents', | |
| icon: Briefcase, | |
| color: 'bg-blue-500', | |
| }, | |
| { | |
| id: 'research-agent', | |
| name: 'Research Agent', | |
| description: 'Conducts deep research, gathers requirements, and analyzes market trends', | |
| icon: Search, | |
| color: 'bg-purple-500', | |
| }, | |
| { | |
| id: 'design-agent', | |
| name: 'Design Agent', | |
| description: 'Creates UI/UX designs, mockups, and design systems', | |
| icon: Palette, | |
| color: 'bg-pink-500', | |
| }, | |
| { | |
| id: 'frontend-agent', | |
| name: 'Frontend Agent', | |
| description: 'Builds responsive user interfaces and implements designs', | |
| icon: Code, | |
| color: 'bg-green-500', | |
| }, | |
| { | |
| id: 'backend-agent', | |
| name: 'Backend Agent', | |
| description: 'Develops APIs, databases, and server-side logic', | |
| icon: Server, | |
| color: 'bg-orange-500', | |
| }, | |
| { | |
| id: 'qa-agent', | |
| name: 'QA Agent', | |
| description: 'Tests functionality, ensures quality, and reports bugs', | |
| icon: Bug, | |
| color: 'bg-red-500', | |
| }, | |
| ] | |
| export default function Home() { | |
| const [selectedAgent, setSelectedAgent] = useState<string | null>(null) | |
| const [showWorkflow, setShowWorkflow] = useState(false) | |
| return ( | |
| <main className="min-h-screen bg-gradient-to-br from-gray-50 to-gray-100 dark:from-gray-900 dark:to-gray-800"> | |
| {/* Header */} | |
| <header className="gradient-bg text-white py-8 px-6 shadow-lg"> | |
| <div className="max-w-7xl mx-auto"> | |
| <h1 className="text-4xl font-bold mb-2">Mastra Multi-Agent System</h1> | |
| <p className="text-gray-100 text-lg"> | |
| AI-powered agents working together to build software projects | |
| </p> | |
| </div> | |
| </header> | |
| <div className="max-w-7xl mx-auto p-6"> | |
| {/* Workflow Toggle */} | |
| <div className="mb-6 flex justify-end"> | |
| <button | |
| onClick={() => setShowWorkflow(!showWorkflow)} | |
| className="flex items-center gap-2 px-4 py-2 bg-white dark:bg-gray-800 rounded-lg shadow-md hover:shadow-lg transition-all" | |
| > | |
| <Workflow className="w-5 h-5" /> | |
| {showWorkflow ? 'Hide Workflow' : 'Show Workflow'} | |
| </button> | |
| </div> | |
| {/* Workflow Visualizer */} | |
| {showWorkflow && ( | |
| <div className="mb-8"> | |
| <WorkflowVisualizer agents={agents} /> | |
| </div> | |
| )} | |
| {/* Agents Grid */} | |
| <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 mb-8"> | |
| {agents.map((agent) => ( | |
| <AgentCard | |
| key={agent.id} | |
| agent={agent} | |
| isSelected={selectedAgent === agent.id} | |
| onClick={() => setSelectedAgent(agent.id)} | |
| /> | |
| ))} | |
| </div> | |
| {/* Chat Interface */} | |
| {selectedAgent && ( | |
| <div className="mt-8"> | |
| <ChatInterface | |
| agentId={selectedAgent} | |
| agentName={agents.find(a => a.id === selectedAgent)?.name || ''} | |
| onClose={() => setSelectedAgent(null)} | |
| /> | |
| </div> | |
| )} | |
| {/* Info Section */} | |
| {!selectedAgent && ( | |
| <div className="bg-white dark:bg-gray-800 rounded-xl shadow-lg p-8 mt-8"> | |
| <h2 className="text-2xl font-bold mb-4">How It Works</h2> | |
| <div className="space-y-4 text-gray-700 dark:text-gray-300"> | |
| <p> | |
| <strong className="text-gray-900 dark:text-white">Project Manager:</strong> Orchestrates the entire development process, delegates tasks to specialized agents, and ensures project alignment. | |
| </p> | |
| <p> | |
| <strong className="text-gray-900 dark:text-white">Research Agent:</strong> Performs comprehensive research on technologies, best practices, and user requirements. | |
| </p> | |
| <p> | |
| <strong className="text-gray-900 dark:text-white">Design Agent:</strong> Creates user-centered designs, wireframes, and maintains design consistency. | |
| </p> | |
| <p> | |
| <strong className="text-gray-900 dark:text-white">Frontend Agent:</strong> Implements responsive interfaces using modern frameworks and best practices. | |
| </p> | |
| <p> | |
| <strong className="text-gray-900 dark:text-white">Backend Agent:</strong> Builds scalable APIs, databases, and handles server-side business logic. | |
| </p> | |
| <p> | |
| <strong className="text-gray-900 dark:text-white">QA Agent:</strong> Ensures code quality through testing, identifies bugs, and validates requirements. | |
| </p> | |
| </div> | |
| <div className="mt-6 p-4 bg-blue-50 dark:bg-blue-900/20 rounded-lg"> | |
| <p className="text-sm text-blue-800 dark:text-blue-200"> | |
| 💡 <strong>Tip:</strong> Select an agent card above to start interacting with it! | |
| </p> | |
| </div> | |
| </div> | |
| )} | |
| </div> | |
| </main> | |
| ) | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 'use client' | |
| import { LucideIcon } from 'lucide-react' | |
| import { ArrowRight } from 'lucide-react' | |
| interface Agent { | |
| id: string | |
| name: string | |
| description: string | |
| icon: LucideIcon | |
| color: string | |
| } | |
| interface WorkflowVisualizerProps { | |
| agents: Agent[] | |
| } | |
| export default function WorkflowVisualizer({ agents }: WorkflowVisualizerProps) { | |
| // Define workflow connections | |
| const workflow = [ | |
| { | |
| from: 'project-manager', | |
| to: 'research-agent', | |
| label: 'Requirements', | |
| }, | |
| { | |
| from: 'research-agent', | |
| to: 'design-agent', | |
| label: 'Findings', | |
| }, | |
| { | |
| from: 'design-agent', | |
| to: 'frontend-agent', | |
| label: 'Designs', | |
| }, | |
| { | |
| from: 'design-agent', | |
| to: 'backend-agent', | |
| label: 'API Specs', | |
| }, | |
| { | |
| from: 'frontend-agent', | |
| to: 'qa-agent', | |
| label: 'UI Code', | |
| }, | |
| { | |
| from: 'backend-agent', | |
| to: 'qa-agent', | |
| label: 'API Code', | |
| }, | |
| { | |
| from: 'qa-agent', | |
| to: 'project-manager', | |
| label: 'Test Results', | |
| }, | |
| ] | |
| return ( | |
| <div className="bg-white dark:bg-gray-800 rounded-xl shadow-lg p-8"> | |
| <h2 className="text-2xl font-bold mb-6 text-gray-900 dark:text-white"> | |
| Agent Workflow | |
| </h2> | |
| {/* Desktop View - Flowchart */} | |
| <div className="hidden md:block"> | |
| <div className="grid grid-cols-3 gap-8"> | |
| {/* Row 1: Project Manager */} | |
| <div className="col-span-3 flex justify-center"> | |
| <WorkflowNode agent={agents[0]} /> | |
| </div> | |
| {/* Arrow Down */} | |
| <div className="col-span-3 flex justify-center"> | |
| <ArrowRight className="rotate-90 text-purple-400" size={32} /> | |
| </div> | |
| {/* Row 2: Research Agent */} | |
| <div className="col-span-3 flex justify-center"> | |
| <WorkflowNode agent={agents[1]} /> | |
| </div> | |
| {/* Arrow Down */} | |
| <div className="col-span-3 flex justify-center"> | |
| <ArrowRight className="rotate-90 text-purple-400" size={32} /> | |
| </div> | |
| {/* Row 3: Design Agent */} | |
| <div className="col-span-3 flex justify-center"> | |
| <WorkflowNode agent={agents[2]} /> | |
| </div> | |
| {/* Arrows to Frontend and Backend */} | |
| <div className="col-span-3 flex justify-center gap-32 my-4"> | |
| <ArrowRight className="rotate-45 text-purple-400" size={32} /> | |
| <ArrowRight className="-rotate-45 text-purple-400" size={32} /> | |
| </div> | |
| {/* Row 4: Frontend and Backend */} | |
| <div className="col-span-3 flex justify-center gap-16"> | |
| <WorkflowNode agent={agents[3]} /> | |
| <WorkflowNode agent={agents[4]} /> | |
| </div> | |
| {/* Arrows to QA */} | |
| <div className="col-span-3 flex justify-center gap-32 my-4"> | |
| <ArrowRight className="-rotate-45 text-purple-400" size={32} /> | |
| <ArrowRight className="rotate-45 text-purple-400" size={32} /> | |
| </div> | |
| {/* Row 5: QA Agent */} | |
| <div className="col-span-3 flex justify-center"> | |
| <WorkflowNode agent={agents[5]} /> | |
| </div> | |
| </div> | |
| </div> | |
| {/* Mobile View - List */} | |
| <div className="md:hidden space-y-4"> | |
| {agents.map((agent, index) => ( | |
| <div key={agent.id}> | |
| <WorkflowNode agent={agent} compact /> | |
| {index < agents.length - 1 && ( | |
| <div className="flex justify-center my-2"> | |
| <ArrowRight className="rotate-90 text-purple-400" size={24} /> | |
| </div> | |
| )} | |
| </div> | |
| ))} | |
| </div> | |
| {/* Legend */} | |
| <div className="mt-8 p-4 bg-purple-50 dark:bg-purple-900/20 rounded-lg"> | |
| <h3 className="font-semibold text-gray-900 dark:text-white mb-2"> | |
| Workflow Process: | |
| </h3> | |
| <ol className="text-sm text-gray-700 dark:text-gray-300 space-y-1 list-decimal list-inside"> | |
| <li>Project Manager defines requirements and coordinates the team</li> | |
| <li>Research Agent conducts deep research and analysis</li> | |
| <li>Design Agent creates UI/UX designs and specifications</li> | |
| <li>Frontend & Backend Agents implement the solution in parallel</li> | |
| <li>QA Agent tests the implementation and reports back</li> | |
| <li>Project Manager reviews and iterates if needed</li> | |
| </ol> | |
| </div> | |
| </div> | |
| ) | |
| } | |
| function WorkflowNode({ agent, compact = false }: { agent: Agent; compact?: boolean }) { | |
| const Icon = agent.icon | |
| return ( | |
| <div | |
| className={`workflow-node bg-white dark:bg-gray-700 rounded-lg shadow-md border-2 border-gray-200 dark:border-gray-600 ${ | |
| compact ? 'p-3' : 'p-4' | |
| }`} | |
| > | |
| <div className="flex items-center gap-3"> | |
| <div className={`${agent.color} p-2 rounded-lg text-white flex-shrink-0`}> | |
| <Icon className={compact ? 'w-4 h-4' : 'w-5 h-5'} /> | |
| </div> | |
| <div> | |
| <h4 | |
| className={`font-semibold text-gray-900 dark:text-white ${ | |
| compact ? 'text-sm' : 'text-base' | |
| }`} | |
| > | |
| {agent.name} | |
| </h4> | |
| {!compact && ( | |
| <p className="text-xs text-gray-600 dark:text-gray-300 mt-1"> | |
| {agent.description.substring(0, 50)}... | |
| </p> | |
| )} | |
| </div> | |
| </div> | |
| </div> | |
| ) | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment