use parking_lot::Mutex;
use prollytree::diff::{AgentPriorityResolver, SemanticMergeResolver};
use prollytree::git::versioned_store::GitVersionedKvStore;
use prollytree::git::worktree::{WorktreeManager, WorktreeVersionedKvStore};
use std::sync::Arc;
use tempfile::TempDir;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("🤖 Multi-Agent Worktree Integration Demo");
println!("=========================================");
let temp_dir = TempDir::new()?;
let repo_path = temp_dir.path();
init_git_repo(repo_path)?;
let mut main_store = GitVersionedKvStore::<16>::init(repo_path.join("main_data"))?;
main_store.insert(
b"shared_config".to_vec(),
br#"{"version": 1, "mode": "production"}"#.to_vec(),
)?;
main_store.insert(b"global_counter".to_vec(), b"0".to_vec())?;
main_store.commit("Initial shared data")?;
println!("✅ Initialized main repository with shared data");
let worktree_manager = WorktreeManager::new(repo_path)?;
let manager_arc = Arc::new(Mutex::new(worktree_manager));
let agent_scenarios = vec![
("agent1", "customer-service", "Handle customer inquiries"),
("agent2", "data-analysis", "Analyze user behavior"),
("agent3", "content-generation", "Generate marketing content"),
];
let mut agent_worktrees = Vec::new();
for (agent_id, session_id, description) in &agent_scenarios {
let agent_path = temp_dir.path().join(format!("{}_workspace", agent_id));
let branch_name = format!("{}-{}", agent_id, session_id);
let worktree_info = {
let mut manager = manager_arc.lock();
manager.add_worktree(&agent_path, &branch_name, true)?
};
let agent_store =
WorktreeVersionedKvStore::<16>::from_worktree(worktree_info, manager_arc.clone())?;
agent_worktrees.push((agent_id.to_string(), agent_store, description.to_string()));
println!(
"🏗️ Created isolated workspace for {} on branch {}",
agent_id, branch_name
);
}
println!("\n📊 Agents performing their tasks...");
for (agent_id, worktree_store, description) in &mut agent_worktrees {
println!(" {} working on: {}", agent_id, description);
match agent_id.as_str() {
"agent1" => {
worktree_store.store_mut().insert(
b"customer:latest".to_vec(),
br#"{"id": "cust_001", "issue": "billing", "priority": "high"}"#.to_vec(),
)?;
worktree_store.store_mut().insert(
b"response_templates".to_vec(),
br#"{"billing": "Thank you for contacting us about billing..."}"#.to_vec(),
)?;
worktree_store
.store_mut()
.commit("Customer service data updates")?;
}
"agent2" => {
worktree_store.store_mut().insert(
b"analytics:daily".to_vec(),
br#"{"users": 1250, "sessions": 3400, "conversion": 0.045}"#.to_vec(),
)?;
worktree_store
.store_mut()
.insert(b"global_counter".to_vec(), b"25".to_vec())?; worktree_store
.store_mut()
.commit("Analytics data updates")?;
}
"agent3" => {
worktree_store.store_mut().insert(
b"content:campaign".to_vec(),
br#"{"title": "Summer Sale", "body": "Get 20% off...", "target": "email"}"#
.to_vec(),
)?;
worktree_store.store_mut().insert(
b"shared_config".to_vec(),
br#"{"version": 1, "mode": "production", "feature_flags": {"new_ui": true}}"#
.to_vec(),
)?; worktree_store
.store_mut()
.commit("Marketing content updates")?;
}
_ => {}
}
}
println!("✅ All agents completed their tasks");
println!("\n🔄 Merging agent work back to main repository...");
println!("\n1️⃣ Simple merge (ignoring conflicts):");
let merge_result1 = agent_worktrees[0]
.1
.merge_to_main(&mut main_store, "Merge customer service updates")?;
println!(" {}", merge_result1);
println!("\n2️⃣ Semantic merge (JSON-aware):");
let semantic_resolver = SemanticMergeResolver::default();
let merge_result2 = agent_worktrees[2].1.merge_to_branch_with_resolver(
&mut main_store,
"main",
&semantic_resolver,
"Merge content generation with semantic resolution",
)?;
println!(" {}", merge_result2);
println!("\n3️⃣ Priority-based merge:");
let mut priority_resolver = AgentPriorityResolver::new();
priority_resolver.set_agent_priority("agent2".to_string(), 10); priority_resolver.set_agent_priority("agent1".to_string(), 5);
let merge_result3 = agent_worktrees[1].1.merge_to_branch_with_resolver(
&mut main_store,
"main",
&priority_resolver,
"Merge analytics with priority resolution",
)?;
println!(" {}", merge_result3);
println!("\n📋 Final merged state:");
if let Some(config_value) = main_store.get(b"shared_config") {
let config_json: serde_json::Value = serde_json::from_slice(&config_value)?;
println!(" • shared_config: {}", config_json);
}
if let Some(counter_value) = main_store.get(b"global_counter") {
let counter_str = String::from_utf8_lossy(&counter_value);
println!(" • global_counter: {}", counter_str);
}
println!("\n🔍 Conflict detection example:");
let mut temp_worktree = agent_worktrees.pop().unwrap().1;
temp_worktree
.store_mut()
.insert(b"global_counter".to_vec(), b"999".to_vec())?; temp_worktree.store_mut().commit("Conflicting update")?;
match temp_worktree.try_merge_to_main(&mut main_store) {
Ok(conflicts) => {
if conflicts.is_empty() {
println!(" ✅ No conflicts detected");
} else {
println!(" ⚠️ {} conflicts detected:", conflicts.len());
for conflict in &conflicts {
println!(" - Key: {}", String::from_utf8_lossy(&conflict.key));
}
}
}
Err(e) => println!(" Error checking conflicts: {}", e),
}
println!("\n🎉 Multi-agent worktree integration demo completed!");
println!("\n💡 Key capabilities demonstrated:");
println!(" • Isolated workspaces for concurrent agents");
println!(" • Git-like branching and merging for AI agent data");
println!(" • Intelligent conflict resolution strategies");
println!(" • Semantic merging for structured JSON data");
println!(" • Priority-based agent coordination");
println!(" • Conflict detection and prevention");
Ok(())
}
fn init_git_repo(repo_path: &std::path::Path) -> Result<(), Box<dyn std::error::Error>> {
use std::process::Command;
Command::new("git")
.args(&["init"])
.current_dir(repo_path)
.output()?;
Command::new("git")
.args(&["config", "user.name", "Multi-Agent Demo"])
.current_dir(repo_path)
.output()?;
Command::new("git")
.args(&["config", "user.email", "demo@multiagent.ai"])
.current_dir(repo_path)
.output()?;
std::fs::write(repo_path.join("README.md"), "# Multi-Agent Repository")?;
Command::new("git")
.args(&["add", "."])
.current_dir(repo_path)
.output()?;
Command::new("git")
.args(&["commit", "-m", "Initial repository setup"])
.current_dir(repo_path)
.output()?;
Ok(())
}