Fix inbox creation issues in agent coordinator
- Fixed Task.new/3 to handle both maps and keyword lists - Added robust inbox existence checking in find_available_agent - Ensure inbox creation during agent registration and task assignment - Add helper function ensure_inbox_exists to avoid crashes
This commit is contained in:
321
test_multi_codebase.exs
Normal file
321
test_multi_codebase.exs
Normal file
@@ -0,0 +1,321 @@
|
||||
#!/usr/bin/env elixir
|
||||
|
||||
# Multi-Codebase Coordination Test Script
|
||||
# This script demonstrates how agents can coordinate across multiple codebases
|
||||
|
||||
Mix.install([
|
||||
{:jason, "~> 1.4"},
|
||||
{:uuid, "~> 1.1"}
|
||||
])
|
||||
|
||||
defmodule MultiCodebaseTest do
|
||||
@moduledoc """
|
||||
Test script for multi-codebase agent coordination functionality.
|
||||
Demonstrates cross-codebase task creation, dependency management, and agent coordination.
|
||||
"""
|
||||
|
||||
def run do
|
||||
IO.puts("=== Multi-Codebase Agent Coordination Test ===\n")
|
||||
|
||||
# Test 1: Register multiple codebases
|
||||
test_codebase_registration()
|
||||
|
||||
# Test 2: Register agents in different codebases
|
||||
test_agent_registration()
|
||||
|
||||
# Test 3: Create tasks within individual codebases
|
||||
test_single_codebase_tasks()
|
||||
|
||||
# Test 4: Create cross-codebase tasks
|
||||
test_cross_codebase_tasks()
|
||||
|
||||
# Test 5: Test cross-codebase dependencies
|
||||
test_codebase_dependencies()
|
||||
|
||||
# Test 6: Verify coordination and task board
|
||||
test_coordination_overview()
|
||||
|
||||
IO.puts("\n=== Test Completed ===")
|
||||
end
|
||||
|
||||
def test_codebase_registration do
|
||||
IO.puts("1. Testing Codebase Registration")
|
||||
IO.puts(" - Registering frontend codebase...")
|
||||
IO.puts(" - Registering backend codebase...")
|
||||
IO.puts(" - Registering shared-lib codebase...")
|
||||
|
||||
frontend_codebase = %{
|
||||
"id" => "frontend-app",
|
||||
"name" => "Frontend Application",
|
||||
"workspace_path" => "/workspace/frontend",
|
||||
"description" => "React-based frontend application",
|
||||
"metadata" => %{
|
||||
"tech_stack" => ["react", "typescript", "tailwind"],
|
||||
"dependencies" => ["backend-api", "shared-lib"]
|
||||
}
|
||||
}
|
||||
|
||||
backend_codebase = %{
|
||||
"id" => "backend-api",
|
||||
"name" => "Backend API",
|
||||
"workspace_path" => "/workspace/backend",
|
||||
"description" => "Node.js API server",
|
||||
"metadata" => %{
|
||||
"tech_stack" => ["nodejs", "express", "mongodb"],
|
||||
"dependencies" => ["shared-lib"]
|
||||
}
|
||||
}
|
||||
|
||||
shared_lib_codebase = %{
|
||||
"id" => "shared-lib",
|
||||
"name" => "Shared Library",
|
||||
"workspace_path" => "/workspace/shared",
|
||||
"description" => "Shared utilities and types",
|
||||
"metadata" => %{
|
||||
"tech_stack" => ["typescript"],
|
||||
"dependencies" => []
|
||||
}
|
||||
}
|
||||
|
||||
# Simulate MCP calls
|
||||
simulate_mcp_call("register_codebase", frontend_codebase)
|
||||
simulate_mcp_call("register_codebase", backend_codebase)
|
||||
simulate_mcp_call("register_codebase", shared_lib_codebase)
|
||||
|
||||
IO.puts(" ✓ All codebases registered successfully\n")
|
||||
end
|
||||
|
||||
def test_agent_registration do
|
||||
IO.puts("2. Testing Agent Registration")
|
||||
|
||||
# Frontend agents
|
||||
frontend_agent1 = %{
|
||||
"name" => "frontend-dev-1",
|
||||
"capabilities" => ["coding", "testing"],
|
||||
"codebase_id" => "frontend-app",
|
||||
"workspace_path" => "/workspace/frontend",
|
||||
"cross_codebase_capable" => true
|
||||
}
|
||||
|
||||
frontend_agent2 = %{
|
||||
"name" => "frontend-dev-2",
|
||||
"capabilities" => ["coding", "review"],
|
||||
"codebase_id" => "frontend-app",
|
||||
"workspace_path" => "/workspace/frontend",
|
||||
"cross_codebase_capable" => false
|
||||
}
|
||||
|
||||
# Backend agents
|
||||
backend_agent1 = %{
|
||||
"name" => "backend-dev-1",
|
||||
"capabilities" => ["coding", "testing", "analysis"],
|
||||
"codebase_id" => "backend-api",
|
||||
"workspace_path" => "/workspace/backend",
|
||||
"cross_codebase_capable" => true
|
||||
}
|
||||
|
||||
# Shared library agent (cross-codebase capable)
|
||||
shared_agent = %{
|
||||
"name" => "shared-lib-dev",
|
||||
"capabilities" => ["coding", "documentation", "review"],
|
||||
"codebase_id" => "shared-lib",
|
||||
"workspace_path" => "/workspace/shared",
|
||||
"cross_codebase_capable" => true
|
||||
}
|
||||
|
||||
agents = [frontend_agent1, frontend_agent2, backend_agent1, shared_agent]
|
||||
|
||||
Enum.each(agents, fn agent ->
|
||||
IO.puts(" - Registering agent: #{agent["name"]} (#{agent["codebase_id"]})")
|
||||
simulate_mcp_call("register_agent", agent)
|
||||
end)
|
||||
|
||||
IO.puts(" ✓ All agents registered successfully\n")
|
||||
end
|
||||
|
||||
def test_single_codebase_tasks do
|
||||
IO.puts("3. Testing Single Codebase Tasks")
|
||||
|
||||
tasks = [
|
||||
%{
|
||||
"title" => "Update user interface components",
|
||||
"description" => "Modernize the login and dashboard components",
|
||||
"codebase_id" => "frontend-app",
|
||||
"file_paths" => ["/src/components/Login.tsx", "/src/components/Dashboard.tsx"],
|
||||
"required_capabilities" => ["coding"],
|
||||
"priority" => "normal"
|
||||
},
|
||||
%{
|
||||
"title" => "Implement user authentication API",
|
||||
"description" => "Create secure user authentication endpoints",
|
||||
"codebase_id" => "backend-api",
|
||||
"file_paths" => ["/src/routes/auth.js", "/src/middleware/auth.js"],
|
||||
"required_capabilities" => ["coding", "testing"],
|
||||
"priority" => "high"
|
||||
},
|
||||
%{
|
||||
"title" => "Add utility functions for date handling",
|
||||
"description" => "Create reusable date utility functions",
|
||||
"codebase_id" => "shared-lib",
|
||||
"file_paths" => ["/src/utils/date.ts", "/src/types/date.ts"],
|
||||
"required_capabilities" => ["coding", "documentation"],
|
||||
"priority" => "normal"
|
||||
}
|
||||
]
|
||||
|
||||
Enum.each(tasks, fn task ->
|
||||
IO.puts(" - Creating task: #{task["title"]} (#{task["codebase_id"]})")
|
||||
simulate_mcp_call("create_task", task)
|
||||
end)
|
||||
|
||||
IO.puts(" ✓ All single-codebase tasks created successfully\n")
|
||||
end
|
||||
|
||||
def test_cross_codebase_tasks do
|
||||
IO.puts("4. Testing Cross-Codebase Tasks")
|
||||
|
||||
# Task that affects multiple codebases
|
||||
cross_codebase_task = %{
|
||||
"title" => "Implement real-time notifications feature",
|
||||
"description" => "Add real-time notifications across frontend and backend",
|
||||
"primary_codebase_id" => "backend-api",
|
||||
"affected_codebases" => ["backend-api", "frontend-app", "shared-lib"],
|
||||
"coordination_strategy" => "sequential"
|
||||
}
|
||||
|
||||
IO.puts(" - Creating cross-codebase task: #{cross_codebase_task["title"]}")
|
||||
IO.puts(" Primary: #{cross_codebase_task["primary_codebase_id"]}")
|
||||
IO.puts(" Affected: #{Enum.join(cross_codebase_task["affected_codebases"], ", ")}")
|
||||
|
||||
simulate_mcp_call("create_cross_codebase_task", cross_codebase_task)
|
||||
|
||||
# Another cross-codebase task with different strategy
|
||||
parallel_task = %{
|
||||
"title" => "Update shared types and interfaces",
|
||||
"description" => "Synchronize type definitions across all codebases",
|
||||
"primary_codebase_id" => "shared-lib",
|
||||
"affected_codebases" => ["shared-lib", "frontend-app", "backend-api"],
|
||||
"coordination_strategy" => "parallel"
|
||||
}
|
||||
|
||||
IO.puts(" - Creating parallel cross-codebase task: #{parallel_task["title"]}")
|
||||
simulate_mcp_call("create_cross_codebase_task", parallel_task)
|
||||
|
||||
IO.puts(" ✓ Cross-codebase tasks created successfully\n")
|
||||
end
|
||||
|
||||
def test_codebase_dependencies do
|
||||
IO.puts("5. Testing Codebase Dependencies")
|
||||
|
||||
dependencies = [
|
||||
%{
|
||||
"source_codebase_id" => "frontend-app",
|
||||
"target_codebase_id" => "backend-api",
|
||||
"dependency_type" => "api_consumption",
|
||||
"metadata" => %{"api_version" => "v1", "endpoints" => ["auth", "users", "notifications"]}
|
||||
},
|
||||
%{
|
||||
"source_codebase_id" => "frontend-app",
|
||||
"target_codebase_id" => "shared-lib",
|
||||
"dependency_type" => "library_import",
|
||||
"metadata" => %{"imports" => ["types", "utils", "constants"]}
|
||||
},
|
||||
%{
|
||||
"source_codebase_id" => "backend-api",
|
||||
"target_codebase_id" => "shared-lib",
|
||||
"dependency_type" => "library_import",
|
||||
"metadata" => %{"imports" => ["types", "validators"]}
|
||||
}
|
||||
]
|
||||
|
||||
Enum.each(dependencies, fn dep ->
|
||||
IO.puts(" - Adding dependency: #{dep["source_codebase_id"]} → #{dep["target_codebase_id"]} (#{dep["dependency_type"]})")
|
||||
simulate_mcp_call("add_codebase_dependency", dep)
|
||||
end)
|
||||
|
||||
IO.puts(" ✓ All codebase dependencies added successfully\n")
|
||||
end
|
||||
|
||||
def test_coordination_overview do
|
||||
IO.puts("6. Testing Coordination Overview")
|
||||
|
||||
IO.puts(" - Getting overall task board...")
|
||||
simulate_mcp_call("get_task_board", %{})
|
||||
|
||||
IO.puts(" - Getting frontend codebase status...")
|
||||
simulate_mcp_call("get_codebase_status", %{"codebase_id" => "frontend-app"})
|
||||
|
||||
IO.puts(" - Getting backend codebase status...")
|
||||
simulate_mcp_call("get_codebase_status", %{"codebase_id" => "backend-api"})
|
||||
|
||||
IO.puts(" - Listing all codebases...")
|
||||
simulate_mcp_call("list_codebases", %{})
|
||||
|
||||
IO.puts(" ✓ Coordination overview retrieved successfully\n")
|
||||
end
|
||||
|
||||
defp simulate_mcp_call(tool_name, arguments) do
|
||||
request = %{
|
||||
"jsonrpc" => "2.0",
|
||||
"id" => UUID.uuid4(),
|
||||
"method" => "tools/call",
|
||||
"params" => %{
|
||||
"name" => tool_name,
|
||||
"arguments" => arguments
|
||||
}
|
||||
}
|
||||
|
||||
# In a real implementation, this would make an actual MCP call
|
||||
# For now, we'll just show the structure
|
||||
IO.puts(" MCP Call: #{tool_name}")
|
||||
IO.puts(" Arguments: #{Jason.encode!(arguments, pretty: true) |> String.replace("\n", "\n ")}")
|
||||
|
||||
# Simulate successful response
|
||||
response = %{
|
||||
"jsonrpc" => "2.0",
|
||||
"id" => request["id"],
|
||||
"result" => %{
|
||||
"content" => [%{
|
||||
"type" => "text",
|
||||
"text" => Jason.encode!(%{"status" => "success", "tool" => tool_name})
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
IO.puts(" Response: success")
|
||||
end
|
||||
|
||||
def simulate_task_flow do
|
||||
IO.puts("\n=== Simulating Multi-Codebase Task Flow ===")
|
||||
|
||||
IO.puts("1. Cross-codebase task created:")
|
||||
IO.puts(" - Main task assigned to backend agent")
|
||||
IO.puts(" - Dependent task created for frontend")
|
||||
IO.puts(" - Dependent task created for shared library")
|
||||
|
||||
IO.puts("\n2. Agent coordination:")
|
||||
IO.puts(" - Backend agent starts implementation")
|
||||
IO.puts(" - Publishes API specification to NATS stream")
|
||||
IO.puts(" - Frontend agent receives notification")
|
||||
IO.puts(" - Shared library agent updates type definitions")
|
||||
|
||||
IO.puts("\n3. File conflict detection:")
|
||||
IO.puts(" - Frontend agent attempts to modify shared types")
|
||||
IO.puts(" - System detects conflict with shared-lib agent's work")
|
||||
IO.puts(" - Task is queued until shared-lib work completes")
|
||||
|
||||
IO.puts("\n4. Cross-codebase synchronization:")
|
||||
IO.puts(" - Shared-lib agent completes type updates")
|
||||
IO.puts(" - Frontend task is automatically unblocked")
|
||||
IO.puts(" - All agents coordinate through NATS streams")
|
||||
|
||||
IO.puts("\n5. Task completion:")
|
||||
IO.puts(" - All subtasks complete successfully")
|
||||
IO.puts(" - Cross-codebase dependencies resolved")
|
||||
IO.puts(" - Coordination system updates task board")
|
||||
end
|
||||
end
|
||||
|
||||
# Run the test
|
||||
MultiCodebaseTest.run()
|
||||
MultiCodebaseTest.simulate_task_flow()
|
||||
Reference in New Issue
Block a user