Files
zclaw_openfang/desktop/src-tauri/src/kernel_commands/a2a.rs
iven 2e5f63be32
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
docs: reorganize docs — archive outdated, create brainstorming folder
- Create docs/brainstorming/ with 5 discussion records (Mar 16 - Apr 7)
- Archive ~30 outdated audit reports (V5-V11) to docs/archive/old-audits/
- Archive superseded analysis docs to docs/archive/old-analysis/
- Archive completed session plans to docs/archive/old-plans/
- Archive old test reports/validations to respective archive folders
- Remove empty directories left after moves
- Keep current docs: TRUTH.md, feature docs, deployment, knowledge-base, superpowers
2026-04-07 09:54:30 +08:00

188 lines
6.2 KiB
Rust

//! 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<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 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<Vec<serde_json::Value>, 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<serde_json::Value> = 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<u64>,
) -> Result<serde_json::Value, 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 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<serde_json::Value, String> {
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<serde_json::Value> = 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,
}))
}