feat(multi-agent): enable Director + butler delegation (Chunk 4)
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

- Enable multi-agent feature by default in desktop build
- Add butler delegation logic: task decomposition, expert assignment
- Add ExpertTask, DelegationResult, butler_delegate() to Director
- Add butler_delegate_task Tauri command bridging Director to frontend
- 13 Director tests passing (6 original + 7 new butler tests)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
iven
2026-04-07 09:21:49 +08:00
parent c7ffba196a
commit e1f3a9719e
4 changed files with 409 additions and 4 deletions

View File

@@ -1,5 +1,6 @@
//! A2A (Agent-to-Agent) commands — gated behind `multi-agent` feature
use serde::Serialize;
use serde_json;
use tauri::State;
use zclaw_types::AgentId;
@@ -109,10 +110,89 @@ pub async fn agent_a2a_delegate_task(
let timeout = timeout_ms.unwrap_or(30_000);
// 30 seconds default
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
// ============================================================
/// Result of butler task delegation (mirrors zclaw_kernel::director::DelegationResult).
#[cfg(feature = "multi-agent")]
#[derive(Debug, Serialize)]
struct ButlerDelegationResponse {
request: String,
tasks: Vec<serde_json::Value>,
success: bool,
summary: String,
}
/// 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,
}))
}