Spaces:
Running
Running
| """ | |
| Minimal Gradio monitor for demo videos. | |
| This is NOT a chat interface - it's a live activity monitor that shows | |
| delegation events happening when Claude Code (or other MCP clients) call | |
| the delegation MCP server. | |
| Purpose: Makes demo videos visually compelling by showing real-time delegation activity. | |
| """ | |
| try: | |
| import gradio as gr | |
| GRADIO_AVAILABLE = True | |
| except ImportError: | |
| GRADIO_AVAILABLE = False | |
| # Mock gr for type hinting if needed, or just handle availability check | |
| gr = None # type: ignore | |
| from pathlib import Path | |
| from datetime import datetime | |
| from collections import deque | |
| # from .persistence import PersistenceManager | |
| class DelegationMonitor: | |
| """Monitors delegation activity for demo visualization.""" | |
| def __init__(self, db_path: Path = Path("data/delegation.db")): | |
| # self.persistence = PersistenceManager(db_path) | |
| self.recent_events = deque(maxlen=20) # Keep last 20 events | |
| def get_recent_activity(self): | |
| """Get recent delegation events for display.""" | |
| return [] | |
| # try: | |
| # history = self.persistence.get_task_history(limit=20) | |
| # return [ | |
| # [ | |
| # entry.timestamp.strftime("%H:%M:%S"), | |
| # entry.orchestrator, | |
| # entry.delegated_to or "N/A", | |
| # "โ " if entry.success else "โ", | |
| # f"{entry.duration:.2f}s" | |
| # ] | |
| # for entry in history | |
| # ] | |
| # except Exception: | |
| # return [] | |
| def get_statistics(self): | |
| """Get delegation statistics for charts.""" | |
| return {"total": 0, "success_rate": 0.0, "avg_duration": 0.0, "agent_usage": {}} | |
| # try: | |
| # stats = self.persistence.get_statistics() | |
| # return { | |
| # "total": stats.get("total_tasks", 0), | |
| # "success_rate": stats.get("success_rate", 0.0), | |
| # "avg_duration": stats.get("avg_duration", 0.0), | |
| # "agent_usage": stats.get("agent_usage", {}), | |
| # } | |
| # except Exception: | |
| # return {"total": 0, "success_rate": 0.0, "avg_duration": 0.0, "agent_usage": {}} | |
| def create_monitor_ui(demo_server=None): | |
| """Create minimal monitoring UI for demo videos (< 150 lines).""" | |
| if not GRADIO_AVAILABLE: | |
| print("Error: Gradio is not installed. Please install with `pip install .[ui]`") | |
| return None | |
| monitor = DelegationMonitor() | |
| with gr.Blocks(title="Delegation MCP Monitor") as app: | |
| gr.Markdown(""" | |
| # ๐ Delegation MCP - Interactive Demo | |
| **Test the intelligent routing system!** Enter a query below to see which agent | |
| the MCP would route it to. Adjust settings to see how configuration affects routing. | |
| --- | |
| """) | |
| # Configuration Section | |
| with gr.Accordion("โ๏ธ Task Routing Configuration", open=False): | |
| gr.Markdown("### 1๏ธโฃ Select Available Agents") | |
| gr.Markdown("*Choose which AI agents are installed and available on your system*") | |
| with gr.Row(): | |
| agent_gemini = gr.Checkbox(label="๐ท Gemini", value=True) | |
| agent_claude = gr.Checkbox(label="๐ฃ Claude", value=True) | |
| agent_aider = gr.Checkbox(label="๐ข Aider", value=True) | |
| agent_copilot = gr.Checkbox(label="๐ต Copilot", value=False) | |
| gr.Markdown("### 2๏ธโฃ Assign Agents to Task Categories") | |
| gr.Markdown("*Configure which agent handles each type of task - same options as install.py*") | |
| with gr.Row(): | |
| with gr.Column(): | |
| security_agent = gr.Dropdown(["gemini", "claude", "aider", "copilot"], value="gemini", label="๐ Security Audits") | |
| architecture_agent = gr.Dropdown(["claude", "gemini", "aider", "copilot"], value="claude", label="๐๏ธ Architecture Design") | |
| refactoring_agent = gr.Dropdown(["aider", "claude", "gemini", "copilot"], value="aider", label="๐ง Refactoring") | |
| quick_fix_agent = gr.Dropdown(["aider", "claude", "gemini", "copilot"], value="aider", label="โก Quick Fixes") | |
| with gr.Column(): | |
| code_review_agent = gr.Dropdown(["claude", "gemini", "aider", "copilot"], value="claude", label="๐ Code Review") | |
| performance_agent = gr.Dropdown(["gemini", "claude", "aider", "copilot"], value="gemini", label="๐ Performance") | |
| testing_agent = gr.Dropdown(["claude", "gemini", "aider", "copilot"], value="claude", label="๐งช Testing") | |
| git_agent = gr.Dropdown(["aider", "claude", "gemini", "copilot"], value="aider", label="๐ฆ Git Operations") | |
| gr.Markdown(""" | |
| **Try it:** Change "Security Audits" from Gemini to Claude, then test a security query! | |
| **Note:** These are the "Balanced" preset defaults - experiment with different combinations! | |
| """) | |
| # Interactive Query Tester | |
| with gr.Row(): | |
| with gr.Column(): | |
| gr.Markdown("### ๐งช Test Routing Intelligence") | |
| query_input = gr.Textbox( | |
| label="Enter your query", | |
| placeholder="e.g., 'Scan my code for SQL injection vulnerabilities'", | |
| lines=3 | |
| ) | |
| submit_btn = gr.Button("๐ Get Routing Decision", variant="primary", size="lg") | |
| # Example queries | |
| with gr.Accordion("๐ก Example Queries", open=True): | |
| gr.Markdown("**Simple Tasks:**") | |
| gr.Examples( | |
| examples=[ | |
| ["Scan this codebase for security vulnerabilities"], | |
| ["Fix the bug causing tests to fail"], | |
| ["Create a pull request with my changes"], | |
| ], | |
| inputs=query_input, | |
| ) | |
| gr.Markdown("**Multi-Agent Workflows:**") | |
| gr.Examples( | |
| examples=[ | |
| ["Scan the codebase for frontend optimization improvements. Generate a report and fix the critical issues. Commit, push, deploy to preview, and test improvements with browser automation"], | |
| ["Audit the authentication system for SQL injection and XSS. Create detailed security report with CVE references. Fix all critical vulnerabilities and update tests"], | |
| ["Analyze API performance bottlenecks using profiling. Optimize database queries and add caching. Generate benchmark report comparing before/after metrics"], | |
| ["Review the entire codebase for code quality issues. Refactor problem areas with proper error handling. Update documentation and create comprehensive test suite"], | |
| ["Design microservices architecture for user management. Implement the service with authentication. Set up CI/CD pipeline and deploy to staging with monitoring"], | |
| ], | |
| inputs=query_input, | |
| ) | |
| with gr.Column(): | |
| gr.Markdown("### ๐ Routing Decision") | |
| decision_output = gr.Textbox( | |
| label="Decision", | |
| lines=2, | |
| interactive=False | |
| ) | |
| task_type_output = gr.Textbox( | |
| label="Task Classification", | |
| lines=1, | |
| interactive=False | |
| ) | |
| complexity_output = gr.Textbox( | |
| label="Complexity Assessment", | |
| lines=1, | |
| interactive=False | |
| ) | |
| reasoning_output = gr.Textbox( | |
| label="Routing Reasoning", | |
| lines=4, | |
| interactive=False | |
| ) | |
| cli_command_output = gr.Textbox( | |
| label="CLI Command (if delegated)", | |
| lines=2, | |
| interactive=False | |
| ) | |
| def update_agent_dropdowns(gemini_enabled, claude_enabled, aider_enabled, copilot_enabled, | |
| sec_current, arch_current, refactor_current, fix_current, | |
| review_current, perf_current, test_current, git_current): | |
| """Update dropdown choices based on selected agents and auto-reassign if needed.""" | |
| # Build list of available agents | |
| available = [] | |
| if gemini_enabled: | |
| available.append("gemini") | |
| if claude_enabled: | |
| available.append("claude") | |
| if aider_enabled: | |
| available.append("aider") | |
| if copilot_enabled: | |
| available.append("copilot") | |
| # If no agents selected, default to all | |
| if not available: | |
| available = ["gemini", "claude", "aider", "copilot"] | |
| # Helper function to get valid value (auto-reassign if current is disabled) | |
| def get_valid_value(current_value): | |
| if current_value in available: | |
| return current_value | |
| # Auto-reassign to first available agent | |
| return available[0] | |
| # Return updates for all 8 dropdowns | |
| return [ | |
| gr.update(choices=available, value=get_valid_value(sec_current)), | |
| gr.update(choices=available, value=get_valid_value(arch_current)), | |
| gr.update(choices=available, value=get_valid_value(refactor_current)), | |
| gr.update(choices=available, value=get_valid_value(fix_current)), | |
| gr.update(choices=available, value=get_valid_value(review_current)), | |
| gr.update(choices=available, value=get_valid_value(perf_current)), | |
| gr.update(choices=available, value=get_valid_value(test_current)), | |
| gr.update(choices=available, value=get_valid_value(git_current)), | |
| ] | |
| async def test_routing(query, sec_agent, arch_agent, refactor_agent, fix_agent, | |
| review_agent, perf_agent, test_agent, git_agent): | |
| """Test routing for a query without executing.""" | |
| if not query.strip(): | |
| return "Please enter a query", "", "", "", "" | |
| if not demo_server: | |
| return "โ Server not initialized", "", "", "", "" | |
| try: | |
| # Map task categories to selected agents | |
| task_agent_map = { | |
| "security_audit": sec_agent, | |
| "vulnerability_scan": sec_agent, | |
| "architecture": arch_agent, | |
| "refactoring": refactor_agent, | |
| "quick_fix": fix_agent, | |
| "code_review": review_agent, | |
| "performance": perf_agent, | |
| "testing": test_agent, | |
| "git_workflow": git_agent, | |
| "github_operations": git_agent, | |
| } | |
| # Temporarily update routing rules based on user selection | |
| from delegation_mcp.config import DelegationRule | |
| demo_server.config.rules.clear() | |
| # Add rules for each task category | |
| for task_type, agent in task_agent_map.items(): | |
| rule = DelegationRule( | |
| delegate_to=agent, | |
| pattern=task_type, | |
| description=f"User configured: {task_type} โ {agent}", | |
| priority=10 | |
| ) | |
| demo_server.config.rules.append(rule) | |
| # Get routing guidance | |
| result = await demo_server.engine.process( | |
| query, | |
| guidance_only=True | |
| ) | |
| # Classify task type and complexity | |
| task_type, timeout = demo_server.engine._classify_task(query) | |
| complexity = demo_server.engine._estimate_task_complexity(query) | |
| # Determine delegation and get reasoning | |
| target, rule = demo_server.engine._determine_delegation(query, None) | |
| # Build reasoning explanation | |
| reasoning_parts = [] | |
| # Complexity assessment | |
| reasoning_parts.append(f"๐ Complexity: {complexity.upper()}") | |
| # Task type detection | |
| query_lower = query.lower() | |
| keywords = { | |
| "security_audit": ["security", "vulnerability", "audit", "cve"], | |
| "architecture": ["architecture", "design", "system design"], | |
| "refactoring": ["refactor", "restructure", "clean up"], | |
| "quick_fix": ["fix", "bug", "error"], | |
| "performance": ["performance", "optimize", "speed"], | |
| "code_review": ["review", "code quality", "best practice"], | |
| } | |
| detected_keywords = [] | |
| for task, kws in keywords.items(): | |
| if task == task_type: | |
| detected_keywords = [kw for kw in kws if kw in query_lower] | |
| break | |
| if detected_keywords: | |
| reasoning_parts.append(f"๐ Keywords: {', '.join(detected_keywords[:3])}") | |
| # Routing strategy | |
| if rule: | |
| if "User configured" in rule.description: | |
| reasoning_parts.append(f"โ๏ธ User Configuration: {task_type} โ {result.delegated_to or 'claude'}") | |
| else: | |
| reasoning_parts.append(f"๐ Matched Rule: {rule.pattern}") | |
| elif complexity == "simple": | |
| reasoning_parts.append("โก Simple task - no delegation overhead needed") | |
| else: | |
| reasoning_parts.append(f"๐ฏ Capability-based routing for {task_type}") | |
| reasoning = "\n".join(reasoning_parts) | |
| # Format decision | |
| if result.delegated_to: | |
| decision = f"โ DELEGATE TO: {result.delegated_to.upper()}" | |
| cli_cmd = f'{result.delegated_to} "{query}"' | |
| else: | |
| decision = "โ HANDLE DIRECTLY (Claude)" | |
| cli_cmd = "N/A - Claude handles internally" | |
| task_info = f"{task_type.replace('_', ' ').title()}" | |
| complexity_info = f"{complexity.title()} (timeout: {timeout}s)" | |
| return decision, task_info, complexity_info, reasoning, cli_cmd | |
| except Exception as e: | |
| return f"โ Error: {str(e)}", "", "", "", "" | |
| submit_btn.click( | |
| fn=test_routing, | |
| inputs=[ | |
| query_input, | |
| security_agent, architecture_agent, refactoring_agent, quick_fix_agent, | |
| code_review_agent, performance_agent, testing_agent, git_agent | |
| ], | |
| outputs=[decision_output, task_type_output, complexity_output, reasoning_output, cli_command_output] | |
| ) | |
| # Wire up checkbox changes to update dropdowns | |
| agent_checkboxes = [agent_gemini, agent_claude, agent_aider, agent_copilot] | |
| task_dropdowns = [security_agent, architecture_agent, refactoring_agent, quick_fix_agent, | |
| code_review_agent, performance_agent, testing_agent, git_agent] | |
| for checkbox in agent_checkboxes: | |
| checkbox.change( | |
| fn=update_agent_dropdowns, | |
| inputs=agent_checkboxes + task_dropdowns, | |
| outputs=task_dropdowns | |
| ) | |
| gr.Markdown("---") | |
| gr.Markdown(""" | |
| ## ๐ Want to Test the Full System? | |
| This demo shows the **routing intelligence** only. To see actual task delegation with AI agents: | |
| ### Option 1: Duplicate This Space | |
| 1. Click the **โฎ** menu (top right) โ **Duplicate Space** | |
| 2. Add your API keys in **Settings โ Secrets**: | |
| - `ANTHROPIC_API_KEY` - For Claude | |
| - `GOOGLE_API_KEY` - For Gemini | |
| 3. Install agent CLIs in your duplicated Space (optional for full functionality) | |
| ### Option 2: Install Locally | |
| ```bash | |
| git clone https://github.com/carlosduplar/multi-agent-mcp.git | |
| cd multi-agent-mcp | |
| pip install -e . | |
| python install.py | |
| ``` | |
| Then configure Claude Code to use the MCP server and start delegating tasks! | |
| --- | |
| ### ๐ Learn More | |
| - **GitHub**: [carlosduplar/multi-agent-mcp](https://github.com/carlosduplar/multi-agent-mcp) | |
| - **Documentation**: Full setup guide in README | |
| - **MCP Hackathon**: Built for MCP 1st Birthday (Winter 2025) | |
| """) | |
| return app | |
| def main(): | |
| """Launch monitor UI.""" | |
| app = create_monitor_ui() | |
| if app: | |
| app.launch(server_name="0.0.0.0", server_port=7860, share=False) | |
| if __name__ == "__main__": | |
| main() | |