diff --git a/crates/goose-cli/src/commands/session.rs b/crates/goose-cli/src/commands/session.rs index 6a36d61d..5d8f8bed 100644 --- a/crates/goose-cli/src/commands/session.rs +++ b/crates/goose-cli/src/commands/session.rs @@ -3,20 +3,27 @@ use goose::session::info::{get_session_info, SessionInfo, SortOrder}; use regex::Regex; use std::fs; -pub fn remove_session(session: &SessionInfo) -> Result<()> { - let should_delete = cliclack::confirm(format!( - "Are you sure you want to delete session `{}`? (yes/no):?", - session.id - )) - .initial_value(true) - .interact()?; - if should_delete { - fs::remove_file(session.path.clone()) - .with_context(|| format!("Failed to remove session file '{}'", session.path))?; - println!("Session `{}` removed.", session.id); - } else { - println!("Skipping deletion of '{}'.", session.id); +pub fn remove_sessions(sessions: Vec) -> Result<()> { + println!("The following sessions will be removed:"); + for session in &sessions { + println!("- {}", session.id); } + + let should_delete = + cliclack::confirm("Are you sure you want to delete all these sessions? (yes/no):") + .initial_value(true) + .interact()?; + + if should_delete { + for session in sessions { + fs::remove_file(session.path.clone()) + .with_context(|| format!("Failed to remove session file '{}'", session.path))?; + println!("Session `{}` removed.", session.id); + } + } else { + println!("Skipping deletion of the sessions."); + } + Ok(()) } @@ -24,37 +31,38 @@ pub fn handle_session_remove(id: String, regex_string: String) -> Result<()> { let sessions = match get_session_info(SortOrder::Descending) { Ok(sessions) => sessions, Err(e) => { - tracing::error!("Failed to remove sessions: {:?}", e); - return Err(anyhow::anyhow!("Failed to remove sessions")); + tracing::error!("Failed to retrieve sessions: {:?}", e); + return Err(anyhow::anyhow!("Failed to retrieve sessions")); } }; + + let matched_sessions: Vec; if !id.is_empty() { - if let Some(session_to_remove) = sessions.iter().find(|s| s.id == id) { - remove_session(session_to_remove)?; + if let Some(session) = sessions.iter().find(|s| s.id == id) { + matched_sessions = vec![session.clone()]; } else { return Err(anyhow::anyhow!("Session '{}' not found.", id)); } } else if !regex_string.is_empty() { - let session_regex: Regex = Regex::new(regex_string.as_str())?; - let mut removed_count = 0; - for session_info in sessions { - if session_regex.is_match(session_info.id.as_str()) { - remove_session(&session_info)?; - removed_count += 1; - } - } - if removed_count == 0 { + let session_regex = Regex::new(®ex_string) + .with_context(|| format!("Invalid regex pattern '{}'", regex_string))?; + matched_sessions = sessions + .into_iter() + .filter(|session| session_regex.is_match(&session.id)) + .collect(); + + if matched_sessions.is_empty() { println!( "Regex string '{}' does not match any sessions", regex_string ); + return Ok(()); } } else { - return Err(anyhow::anyhow!( - "Neither --regex nor --session-name flags provided." - )); + return Err(anyhow::anyhow!("Neither --regex nor --id flags provided.")); } - Ok(()) + + remove_sessions(matched_sessions) } pub fn handle_session_list(verbose: bool, format: String, ascending: bool) -> Result<()> { diff --git a/crates/goose/src/session/info.rs b/crates/goose/src/session/info.rs index 44c2ca4f..f44794d3 100644 --- a/crates/goose/src/session/info.rs +++ b/crates/goose/src/session/info.rs @@ -4,7 +4,7 @@ use std::cmp::Ordering; use crate::session::{self, SessionMetadata}; -#[derive(Serialize)] +#[derive(Clone, Serialize)] pub struct SessionInfo { pub id: String, pub path: String,