//! A2A (Agent-to-Agent) commands — gated behind `multi-agent` feature use serde_json; use tauri::State; use zclaw_types::AgentId; use super::KernelState; // ============================================================ // A2A (Agent-to-Agent) Commands — gated behind multi-agent feature // ============================================================ #[cfg(feature = "multi-agent")] /// Send a direct A2A message from one agent to another // @connected #[tauri::command] pub async fn agent_a2a_send( state: State<'_, KernelState>, from: String, to: String, payload: serde_json::Value, message_type: Option, ) -> Result<(), String> { let kernel_lock = state.lock().await; let kernel = kernel_lock.as_ref() .ok_or_else(|| "Kernel not initialized. Call kernel_init first.".to_string())?; let from_id: AgentId = from.parse() .map_err(|_| format!("Invalid from agent ID: {}", from))?; let to_id: AgentId = to.parse() .map_err(|_| format!("Invalid to agent ID: {}", to))?; let msg_type = message_type.map(|mt| match mt.as_str() { "request" => zclaw_kernel::A2aMessageType::Request, "notification" => zclaw_kernel::A2aMessageType::Notification, "task" => zclaw_kernel::A2aMessageType::Task, _ => zclaw_kernel::A2aMessageType::Notification, }); kernel.a2a_send(&from_id, &to_id, payload, msg_type).await .map_err(|e| format!("A2A send failed: {}", e))?; Ok(()) } /// Broadcast a message from one agent to all other agents #[cfg(feature = "multi-agent")] // @connected #[tauri::command] pub async fn agent_a2a_broadcast( state: State<'_, KernelState>, from: String, payload: serde_json::Value, ) -> Result<(), String> { let kernel_lock = state.lock().await; let kernel = kernel_lock.as_ref() .ok_or_else(|| "Kernel not initialized. Call kernel_init first.".to_string())?; let from_id: AgentId = from.parse() .map_err(|_| format!("Invalid from agent ID: {}", from))?; kernel.a2a_broadcast(&from_id, payload).await .map_err(|e| format!("A2A broadcast failed: {}", e))?; Ok(()) } /// Discover agents with a specific capability #[cfg(feature = "multi-agent")] // @connected #[tauri::command] pub async fn agent_a2a_discover( state: State<'_, KernelState>, capability: String, ) -> Result, String> { let kernel_lock = state.lock().await; let kernel = kernel_lock.as_ref() .ok_or_else(|| "Kernel not initialized. Call kernel_init first.".to_string())?; let profiles = kernel.a2a_discover(&capability).await .map_err(|e| format!("A2A discover failed: {}", e))?; let result: Vec = profiles.iter() .filter_map(|p| serde_json::to_value(p).ok()) .collect(); Ok(result) } /// Delegate a task to another agent and wait for response #[cfg(feature = "multi-agent")] // @connected #[tauri::command] pub async fn agent_a2a_delegate_task( state: State<'_, KernelState>, from: String, to: String, task: String, timeout_ms: Option, ) -> Result { let kernel_lock = state.lock().await; let kernel = kernel_lock.as_ref() .ok_or_else(|| "Kernel not initialized. Call kernel_init first.".to_string())?; let from_id: AgentId = from.parse() .map_err(|_| format!("Invalid from agent ID: {}", from))?; let to_id: AgentId = to.parse() .map_err(|_| format!("Invalid to agent ID: {}", to))?; let timeout = timeout_ms.unwrap_or(30_000); let response = kernel.a2a_delegate_task(&from_id, &to_id, task, timeout).await .map_err(|e| format!("A2A task delegation failed: {}", e))?; Ok(response) } // ============================================================ // Butler Delegation Command — multi-agent feature // ============================================================ /// Butler delegates a user request to expert agents via the Director. #[cfg(feature = "multi-agent")] // @connected #[tauri::command] pub async fn butler_delegate_task( state: State<'_, KernelState>, request: String, ) -> Result { use zclaw_kernel::director::{Director, DirectorConfig, DirectorAgent, AgentRole}; let kernel_lock = state.lock().await; let kernel = kernel_lock.as_ref() .ok_or_else(|| "Kernel not initialized. Call kernel_init first.".to_string())?; // Create a Director for this delegation let director = Director::new(DirectorConfig::default()); // Register active agents from kernel as experts let agents = kernel.list_agents(); for agent in agents { let persona = agent.system_prompt.clone() .or(agent.soul.clone()) .unwrap_or_default(); let director_agent = DirectorAgent::new( agent.id.clone(), agent.name.clone(), AgentRole::Expert, persona, ); director.register_agent(director_agent).await; } drop(kernel_lock); let result = director.butler_delegate(&request).await .map_err(|e| format!("Butler delegation failed: {}", e))?; // Convert to JSON-serializable response let tasks: Vec = result.tasks.iter().map(|t| { serde_json::json!({ "id": t.id, "description": t.description, "category": t.category, "priority": t.priority, "status": match t.status { zclaw_kernel::director::ExpertTaskStatus::Pending => "pending", zclaw_kernel::director::ExpertTaskStatus::Assigned => "assigned", zclaw_kernel::director::ExpertTaskStatus::InProgress => "in_progress", zclaw_kernel::director::ExpertTaskStatus::Completed => "completed", zclaw_kernel::director::ExpertTaskStatus::Failed => "failed", }, "assigned_expert": t.assigned_expert.as_ref().map(|e| serde_json::json!({ "id": e.id.to_string(), "name": e.name, "role": e.role.as_str(), })), }) }).collect(); Ok(serde_json::json!({ "request": result.request, "tasks": tasks, "success": result.success, "summary": result.summary, })) }