Add remove session capacity (#2281)

Co-authored-by: Shou En Hsiao <shouen_hsiao@apple.com>
This commit is contained in:
Shawn Hsiao
2025-04-22 15:51:33 -07:00
committed by GitHub
parent 91f3088af0
commit 36f1c602eb
4 changed files with 76 additions and 2 deletions

1
Cargo.lock generated
View File

@@ -2486,6 +2486,7 @@ dependencies = [
"mcp-server",
"once_cell",
"rand",
"regex",
"reqwest 0.12.12",
"rustyline",
"serde",

View File

@@ -51,6 +51,7 @@ once_cell = "1.20.2"
shlex = "1.3.0"
async-trait = "0.1.86"
base64 = "0.22.1"
regex = "1.11.1"
[target.'cfg(target_os = "windows")'.dependencies]
winapi = { version = "0.3", features = ["wincred"] }

View File

@@ -8,7 +8,7 @@ use crate::commands::configure::handle_configure;
use crate::commands::info::handle_info;
use crate::commands::mcp::run_server;
use crate::commands::recipe::{handle_deeplink, handle_validate};
use crate::commands::session::handle_session_list;
use crate::commands::session::{handle_session_list, handle_session_remove};
use crate::logging::setup_logging;
use crate::recipe::load_recipe;
use crate::session;
@@ -74,6 +74,18 @@ enum SessionCommand {
)]
format: String,
},
#[command(about = "Remove sessions")]
Remove {
#[arg(short, long, help = "session id to be removed", default_value = "")]
id: String,
#[arg(
short,
long,
help = "regex for removing matched session",
default_value = ""
)]
regex: String,
},
}
#[derive(Subcommand)]
@@ -385,6 +397,10 @@ pub async fn cli() -> Result<()> {
handle_session_list(verbose, format)?;
Ok(())
}
Some(SessionCommand::Remove { id, regex }) => {
handle_session_remove(id, regex)?;
return Ok(());
}
None => {
// Run session command by default
let mut session = build_session(SessionBuilderConfig {

View File

@@ -1,5 +1,61 @@
use anyhow::Result;
use anyhow::{Context, Result};
use goose::session::info::{get_session_info, SessionInfo};
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);
}
Ok(())
}
pub fn handle_session_remove(id: String, regex_string: String) -> Result<()> {
let sessions = match get_session_info() {
Ok(sessions) => sessions,
Err(e) => {
tracing::error!("Failed to remove sessions: {:?}", e);
return Err(anyhow::anyhow!("Failed to remove sessions"));
}
};
if !id.is_empty() {
if let Some(session_to_remove) = sessions.iter().find(|s| s.id == id) {
remove_session(session_to_remove)?;
} 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 {
println!(
"Regex string '{}' does not match any sessions",
regex_string
);
}
} else {
return Err(anyhow::anyhow!(
"Neither --regex nor --session-name flags provided."
));
}
Ok(())
}
pub fn handle_session_list(verbose: bool, format: String) -> Result<()> {
let sessions = match get_session_info() {