diff --git a/crates/zclaw-kernel/src/kernel.rs b/crates/zclaw-kernel/src/kernel.rs index bcc21f1..73aa7cf 100644 --- a/crates/zclaw-kernel/src/kernel.rs +++ b/crates/zclaw-kernel/src/kernel.rs @@ -481,6 +481,11 @@ impl Kernel { self.registry.get_info(id) } + /// Get agent config (for export) + pub fn get_agent_config(&self, id: &AgentId) -> Option { + self.registry.get(id) + } + /// Send a message to an agent pub async fn send_message(&self, agent_id: &AgentId, message: String) -> Result { let agent_config = self.registry.get(agent_id) diff --git a/desktop/src-tauri/src/kernel_commands.rs b/desktop/src-tauri/src/kernel_commands.rs index 7f57e1a..242760d 100644 --- a/desktop/src-tauri/src/kernel_commands.rs +++ b/desktop/src-tauri/src/kernel_commands.rs @@ -378,6 +378,54 @@ pub async fn agent_delete( .map_err(|e| format!("Failed to delete agent: {}", e)) } +/// Export an agent configuration as JSON +#[tauri::command] +pub async fn agent_export( + state: State<'_, KernelState>, + agent_id: String, +) -> Result { + let agent_id = validate_agent_id(&agent_id)?; + + 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 id: AgentId = agent_id.parse() + .map_err(|_| "Invalid agent ID format".to_string())?; + + let config = kernel.get_agent_config(&id) + .ok_or_else(|| format!("Agent not found: {}", agent_id))?; + + serde_json::to_string_pretty(&config) + .map_err(|e| format!("Failed to serialize agent config: {}", e)) +} + +/// Import an agent from JSON configuration +#[tauri::command] +pub async fn agent_import( + state: State<'_, KernelState>, + config_json: String, +) -> Result { + validate_string_length(&config_json, "config_json", 1_000_000) + .map_err(|e| format!("{}", e))?; + + let mut config: AgentConfig = serde_json::from_str(&config_json) + .map_err(|e| format!("Invalid agent config JSON: {}", e))?; + + // Regenerate ID to avoid collisions + config.id = AgentId::new(); + + 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 new_id = kernel.spawn_agent(config).await + .map_err(|e| format!("Failed to import agent: {}", e))?; + + kernel.get_agent(&new_id) + .ok_or_else(|| "Agent was created but could not be retrieved".to_string()) +} + /// Send a message to an agent #[tauri::command] pub async fn agent_chat( diff --git a/desktop/src-tauri/src/lib.rs b/desktop/src-tauri/src/lib.rs index b25f102..860bcae 100644 --- a/desktop/src-tauri/src/lib.rs +++ b/desktop/src-tauri/src/lib.rs @@ -1331,6 +1331,8 @@ pub fn run() { kernel_commands::agent_list, kernel_commands::agent_get, kernel_commands::agent_delete, + kernel_commands::agent_export, + kernel_commands::agent_import, kernel_commands::agent_chat, kernel_commands::agent_chat_stream, // Skills commands (dynamic discovery)