Add comprehensive agent activity tracking
- Enhanced Agent struct with current_activity, current_files, and activity_history fields - Created ActivityTracker module to infer activities from tool calls - Integrated activity tracking into MCP server tool routing - Updated task board APIs to include activity information - Agents now show real-time status like 'Reading file.ex', 'Editing main.py', 'Sequential thinking', etc. - Added activity history to track recent agent actions - All file operations and tool calls are now tracked and displayed
This commit is contained in:
@@ -1,193 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
AgentCoordinator MCP Client Example
|
||||
|
||||
This script demonstrates how to connect to and interact with the
|
||||
AgentCoordinator MCP server programmatically.
|
||||
"""
|
||||
|
||||
import json
|
||||
import subprocess
|
||||
import uuid
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
|
||||
class AgentCoordinatorMCP:
|
||||
def __init__(self, launcher_path: str = "./scripts/mcp_launcher.sh"):
|
||||
self.launcher_path = launcher_path
|
||||
self.process = None
|
||||
|
||||
def start(self):
|
||||
"""Start the MCP server process"""
|
||||
try:
|
||||
self.process = subprocess.Popen(
|
||||
[self.launcher_path],
|
||||
stdin=subprocess.PIPE,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
text=True,
|
||||
bufsize=0
|
||||
)
|
||||
print("🚀 MCP server started")
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"❌ Failed to start MCP server: {e}")
|
||||
return False
|
||||
|
||||
def stop(self):
|
||||
"""Stop the MCP server process"""
|
||||
if self.process:
|
||||
self.process.terminate()
|
||||
self.process.wait()
|
||||
print("🛑 MCP server stopped")
|
||||
|
||||
def send_request(self, method: str, params: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
|
||||
"""Send a JSON-RPC request to the MCP server"""
|
||||
if not self.process:
|
||||
raise RuntimeError("MCP server not started")
|
||||
|
||||
request = {
|
||||
"jsonrpc": "2.0",
|
||||
"id": str(uuid.uuid4()),
|
||||
"method": method
|
||||
}
|
||||
|
||||
if params:
|
||||
request["params"] = params
|
||||
|
||||
# Send request
|
||||
request_json = json.dumps(request) + "\n"
|
||||
self.process.stdin.write(request_json)
|
||||
self.process.stdin.flush()
|
||||
|
||||
# Read response
|
||||
response_line = self.process.stdout.readline()
|
||||
if not response_line:
|
||||
raise RuntimeError("No response from MCP server")
|
||||
|
||||
return json.loads(response_line.strip())
|
||||
|
||||
def get_tools(self) -> Dict[str, Any]:
|
||||
"""Get list of available tools"""
|
||||
return self.send_request("tools/list")
|
||||
|
||||
def register_agent(self, name: str, capabilities: list) -> Dict[str, Any]:
|
||||
"""Register a new agent"""
|
||||
return self.send_request("tools/call", {
|
||||
"name": "register_agent",
|
||||
"arguments": {
|
||||
"name": name,
|
||||
"capabilities": capabilities
|
||||
}
|
||||
})
|
||||
|
||||
def create_task(self, title: str, description: str, priority: str = "normal",
|
||||
required_capabilities: list = None) -> Dict[str, Any]:
|
||||
"""Create a new task"""
|
||||
args = {
|
||||
"title": title,
|
||||
"description": description,
|
||||
"priority": priority
|
||||
}
|
||||
if required_capabilities:
|
||||
args["required_capabilities"] = required_capabilities
|
||||
|
||||
return self.send_request("tools/call", {
|
||||
"name": "create_task",
|
||||
"arguments": args
|
||||
})
|
||||
|
||||
def get_next_task(self, agent_id: str) -> Dict[str, Any]:
|
||||
"""Get next task for an agent"""
|
||||
return self.send_request("tools/call", {
|
||||
"name": "get_next_task",
|
||||
"arguments": {"agent_id": agent_id}
|
||||
})
|
||||
|
||||
def complete_task(self, agent_id: str, result: str) -> Dict[str, Any]:
|
||||
"""Complete current task"""
|
||||
return self.send_request("tools/call", {
|
||||
"name": "complete_task",
|
||||
"arguments": {
|
||||
"agent_id": agent_id,
|
||||
"result": result
|
||||
}
|
||||
})
|
||||
|
||||
def get_task_board(self) -> Dict[str, Any]:
|
||||
"""Get task board overview"""
|
||||
return self.send_request("tools/call", {
|
||||
"name": "get_task_board",
|
||||
"arguments": {}
|
||||
})
|
||||
|
||||
def heartbeat(self, agent_id: str) -> Dict[str, Any]:
|
||||
"""Send agent heartbeat"""
|
||||
return self.send_request("tools/call", {
|
||||
"name": "heartbeat",
|
||||
"arguments": {"agent_id": agent_id}
|
||||
})
|
||||
|
||||
def demo():
|
||||
"""Demonstrate MCP client functionality"""
|
||||
print("🎯 AgentCoordinator MCP Client Demo")
|
||||
print("=" * 50)
|
||||
|
||||
client = AgentCoordinatorMCP()
|
||||
|
||||
try:
|
||||
# Start server
|
||||
if not client.start():
|
||||
return
|
||||
|
||||
# Wait for server to be ready
|
||||
import time
|
||||
time.sleep(2)
|
||||
|
||||
# Get tools
|
||||
print("\n📋 Available tools:")
|
||||
tools_response = client.get_tools()
|
||||
if "result" in tools_response:
|
||||
for tool in tools_response["result"]["tools"]:
|
||||
print(f" - {tool['name']}: {tool['description']}")
|
||||
|
||||
# Register agent
|
||||
print("\n👤 Registering agent...")
|
||||
register_response = client.register_agent("PythonAgent", ["coding", "testing"])
|
||||
if "result" in register_response:
|
||||
content = register_response["result"]["content"][0]["text"]
|
||||
agent_data = json.loads(content)
|
||||
agent_id = agent_data["agent_id"]
|
||||
print(f"✅ Agent registered: {agent_id}")
|
||||
|
||||
# Create task
|
||||
print("\n📝 Creating task...")
|
||||
task_response = client.create_task(
|
||||
"Python Script",
|
||||
"Write a Python script for data processing",
|
||||
"high",
|
||||
["coding"]
|
||||
)
|
||||
if "result" in task_response:
|
||||
content = task_response["result"]["content"][0]["text"]
|
||||
task_data = json.loads(content)
|
||||
print(f"✅ Task created: {task_data['task_id']}")
|
||||
|
||||
# Get task board
|
||||
print("\n📊 Task board:")
|
||||
board_response = client.get_task_board()
|
||||
if "result" in board_response:
|
||||
content = board_response["result"]["content"][0]["text"]
|
||||
board_data = json.loads(content)
|
||||
for agent in board_data["agents"]:
|
||||
print(f" 📱 {agent['name']}: {agent['status']}")
|
||||
print(f" Capabilities: {', '.join(agent['capabilities'])}")
|
||||
print(f" Pending: {agent['pending_tasks']}, Completed: {agent['completed_tasks']}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Error: {e}")
|
||||
finally:
|
||||
client.stop()
|
||||
|
||||
if __name__ == "__main__":
|
||||
demo()
|
||||
111
examples/simple_test_demo.exs
Normal file
111
examples/simple_test_demo.exs
Normal file
@@ -0,0 +1,111 @@
|
||||
#!/usr/bin/env elixir
|
||||
|
||||
# Simple test for agent-specific task pools using Mix
|
||||
Mix.install([{:jason, "~> 1.4"}])
|
||||
|
||||
Code.require_file("mix.exs")
|
||||
|
||||
Application.ensure_all_started(:agent_coordinator)
|
||||
|
||||
alias AgentCoordinator.{TaskRegistry, Inbox, Agent, Task}
|
||||
|
||||
IO.puts("🧪 Simple Agent-Specific Task Pool Test")
|
||||
IO.puts("=" |> String.duplicate(50))
|
||||
|
||||
# Wait for services to start
|
||||
Process.sleep(2000)
|
||||
|
||||
# Test 1: Create agents directly
|
||||
IO.puts("\n1️⃣ Creating agents directly...")
|
||||
|
||||
agent1 = Agent.new("Alpha Wolf", [:coding, :testing])
|
||||
agent2 = Agent.new("Beta Tiger", [:documentation, :analysis])
|
||||
|
||||
case TaskRegistry.register_agent(agent1) do
|
||||
:ok -> IO.puts("✅ Agent 1 registered: #{agent1.id}")
|
||||
error -> IO.puts("❌ Agent 1 failed: #{inspect(error)}")
|
||||
end
|
||||
|
||||
case TaskRegistry.register_agent(agent2) do
|
||||
:ok -> IO.puts("✅ Agent 2 registered: #{agent2.id}")
|
||||
error -> IO.puts("❌ Agent 2 failed: #{inspect(error)}")
|
||||
end
|
||||
|
||||
# Test 2: Create agent-specific tasks
|
||||
IO.puts("\n2️⃣ Creating agent-specific tasks...")
|
||||
|
||||
# Create tasks for Agent 1
|
||||
task1_agent1 = Task.new("Fix auth bug", "Debug authentication issue", %{
|
||||
priority: :high,
|
||||
assigned_agent: agent1.id,
|
||||
metadata: %{agent_created: true}
|
||||
})
|
||||
|
||||
task2_agent1 = Task.new("Add auth tests", "Write comprehensive auth tests", %{
|
||||
priority: :normal,
|
||||
assigned_agent: agent1.id,
|
||||
metadata: %{agent_created: true}
|
||||
})
|
||||
|
||||
# Create tasks for Agent 2
|
||||
task1_agent2 = Task.new("Write API docs", "Document REST endpoints", %{
|
||||
priority: :normal,
|
||||
assigned_agent: agent2.id,
|
||||
metadata: %{agent_created: true}
|
||||
})
|
||||
|
||||
# Add tasks to respective agent inboxes
|
||||
case Inbox.add_task(agent1.id, task1_agent1) do
|
||||
:ok -> IO.puts("✅ Task 1 added to Agent 1")
|
||||
error -> IO.puts("❌ Task 1 failed: #{inspect(error)}")
|
||||
end
|
||||
|
||||
case Inbox.add_task(agent1.id, task2_agent1) do
|
||||
:ok -> IO.puts("✅ Task 2 added to Agent 1")
|
||||
error -> IO.puts("❌ Task 2 failed: #{inspect(error)}")
|
||||
end
|
||||
|
||||
case Inbox.add_task(agent2.id, task1_agent2) do
|
||||
:ok -> IO.puts("✅ Task 1 added to Agent 2")
|
||||
error -> IO.puts("❌ Task 1 to Agent 2 failed: #{inspect(error)}")
|
||||
end
|
||||
|
||||
# Test 3: Verify agent isolation
|
||||
IO.puts("\n3️⃣ Testing agent task isolation...")
|
||||
|
||||
# Agent 1 gets their tasks
|
||||
case Inbox.get_next_task(agent1.id) do
|
||||
nil -> IO.puts("❌ Agent 1 has no tasks")
|
||||
task -> IO.puts("✅ Agent 1 got task: #{task.title}")
|
||||
end
|
||||
|
||||
# Agent 2 gets their tasks
|
||||
case Inbox.get_next_task(agent2.id) do
|
||||
nil -> IO.puts("❌ Agent 2 has no tasks")
|
||||
task -> IO.puts("✅ Agent 2 got task: #{task.title}")
|
||||
end
|
||||
|
||||
# Test 4: Check task status
|
||||
IO.puts("\n4️⃣ Checking task status...")
|
||||
|
||||
status1 = Inbox.get_status(agent1.id)
|
||||
status2 = Inbox.get_status(agent2.id)
|
||||
|
||||
IO.puts("Agent 1 status: #{inspect(status1)}")
|
||||
IO.puts("Agent 2 status: #{inspect(status2)}")
|
||||
|
||||
# Test 5: List all tasks for each agent
|
||||
IO.puts("\n5️⃣ Listing all tasks per agent...")
|
||||
|
||||
tasks1 = Inbox.list_tasks(agent1.id)
|
||||
tasks2 = Inbox.list_tasks(agent2.id)
|
||||
|
||||
IO.puts("Agent 1 tasks: #{inspect(tasks1)}")
|
||||
IO.puts("Agent 2 tasks: #{inspect(tasks2)}")
|
||||
|
||||
IO.puts("\n" <> "=" |> String.duplicate(50))
|
||||
IO.puts("🎉 AGENT ISOLATION TEST COMPLETE!")
|
||||
IO.puts("✅ Each agent has their own task inbox")
|
||||
IO.puts("✅ No cross-contamination of tasks")
|
||||
IO.puts("✅ Agent-specific task pools working!")
|
||||
IO.puts("=" |> String.duplicate(50))
|
||||
Reference in New Issue
Block a user