(
state: State<'_, AppState>,
request: CreateSubagentRequest,
)
| 278 | |
| 279 | #[tauri::command] |
| 280 | pub async fn create_subagent( |
| 281 | state: State<'_, AppState>, |
| 282 | request: CreateSubagentRequest, |
| 283 | ) -> Result<(), String> { |
| 284 | let name = request.name.trim(); |
| 285 | validate_agent_name(name)?; |
| 286 | let workspace = workspace_root_from_request(request.workspace_path.as_deref()); |
| 287 | |
| 288 | if request.level == SubagentLevel::Project && workspace.is_none() { |
| 289 | return Err("Project-level Agent requires opening a workspace first".to_string()); |
| 290 | } |
| 291 | |
| 292 | let modes = state.agent_registry.get_modes_info().await; |
| 293 | let subagents = state |
| 294 | .agent_registry |
| 295 | .get_subagents_info(workspace.as_deref()) |
| 296 | .await; |
| 297 | let existing: std::collections::HashSet<_> = modes |
| 298 | .iter() |
| 299 | .map(|m| m.id.as_str().to_lowercase()) |
| 300 | .chain(subagents.iter().map(|s| s.id.as_str().to_lowercase())) |
| 301 | .collect(); |
| 302 | if existing.contains(name.to_lowercase().as_str()) { |
| 303 | return Err(format!( |
| 304 | "Name '{}' conflicts with existing mode or Sub Agent", |
| 305 | name |
| 306 | )); |
| 307 | } |
| 308 | |
| 309 | let pm = state.workspace_service.path_manager(); |
| 310 | let agents_dir = match request.level { |
| 311 | SubagentLevel::User => pm.user_agents_dir(), |
| 312 | SubagentLevel::Project => { |
| 313 | let root = workspace.as_deref().ok_or("Workspace path not available")?; |
| 314 | pm.project_agents_dir(root) |
| 315 | } |
| 316 | }; |
| 317 | |
| 318 | std::fs::create_dir_all(&agents_dir) |
| 319 | .map_err(|e| format!("Failed to create directory: {}", e))?; |
| 320 | |
| 321 | let tools = request.tools.filter(|t| !t.is_empty()).unwrap_or_else(|| { |
| 322 | vec![ |
| 323 | "LS".to_string(), |
| 324 | "Read".to_string(), |
| 325 | "Glob".to_string(), |
| 326 | "Grep".to_string(), |
| 327 | ] |
| 328 | }); |
| 329 | let kind = match request.level { |
| 330 | SubagentLevel::User => CustomSubagentKind::User, |
| 331 | SubagentLevel::Project => CustomSubagentKind::Project, |
| 332 | }; |
| 333 | let file_path = agents_dir.join(format!("{}.md", name.to_lowercase())); |
| 334 | let path_str = file_path.to_string_lossy().to_string(); |
| 335 | if file_path.exists() { |
| 336 | return Err(format!("File '{}' already exists", path_str)); |
| 337 | } |
nothing calls this directly
no test coverage detected