From 97ff0cdd039cfa3f241f97c4506409bca144e6b2 Mon Sep 17 00:00:00 2001 From: Lily Delalande <119957291+lily-de@users.noreply.github.com> Date: Wed, 7 May 2025 12:46:42 -0400 Subject: [PATCH] cli: add summarize slash command (#2464) --- crates/goose-cli/src/session/input.rs | 15 +++++++++ crates/goose-cli/src/session/mod.rs | 47 +++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/crates/goose-cli/src/session/input.rs b/crates/goose-cli/src/session/input.rs index cdca703b..c4049674 100644 --- a/crates/goose-cli/src/session/input.rs +++ b/crates/goose-cli/src/session/input.rs @@ -18,6 +18,7 @@ pub enum InputResult { Plan(PlanCommandOptions), EndPlan, Recipe(Option), + Summarize, } #[derive(Debug)] @@ -91,6 +92,7 @@ fn handle_slash_command(input: &str) -> Option { const CMD_PLAN: &str = "/plan"; const CMD_ENDPLAN: &str = "/endplan"; const CMD_RECIPE: &str = "/recipe"; + const CMD_SUMMARIZE: &str = "/summarize"; match input { "/exit" | "/quit" => Some(InputResult::Exit), @@ -133,6 +135,7 @@ fn handle_slash_command(input: &str) -> Option { s if s.starts_with(CMD_PLAN) => parse_plan_command(s[CMD_PLAN.len()..].trim().to_string()), s if s == CMD_ENDPLAN => Some(InputResult::EndPlan), s if s.starts_with(CMD_RECIPE) => parse_recipe_command(s), + s if s == CMD_SUMMARIZE => Some(InputResult::Summarize), _ => None, } } @@ -241,6 +244,7 @@ fn print_help() { /endplan - Exit plan mode and return to 'normal' goose mode. /recipe [filepath] - Generate a recipe from the current conversation and save it to the specified filepath (must end with .yaml). If no filepath is provided, it will be saved to ./recipe.yaml. +/summarize - Summarize the current conversation to reduce context length while preserving key information. /? or /help - Display this help message Navigation: @@ -474,4 +478,15 @@ mod tests { let result = handle_slash_command("/recipe /path/to/file.txt"); assert!(matches!(result, Some(InputResult::Retry))); } + + #[test] + fn test_summarize_command() { + // Test the summarize command + let result = handle_slash_command("/summarize"); + assert!(matches!(result, Some(InputResult::Summarize))); + + // Test with whitespace + let result = handle_slash_command(" /summarize "); + assert!(matches!(result, Some(InputResult::Summarize))); + } } diff --git a/crates/goose-cli/src/session/mod.rs b/crates/goose-cli/src/session/mod.rs index 368274ce..04d92834 100644 --- a/crates/goose-cli/src/session/mod.rs +++ b/crates/goose-cli/src/session/mod.rs @@ -503,6 +503,53 @@ impl Session { } } + continue; + } + InputResult::Summarize => { + save_history(&mut editor); + + let prompt = "Are you sure you want to summarize this conversation? This will condense the message history."; + let should_summarize = + cliclack::confirm(prompt).initial_value(true).interact()?; + + if should_summarize { + println!("{}", console::style("Summarizing conversation...").yellow()); + output::show_thinking(); + + // Get the provider for summarization + let provider = self.agent.provider().await?; + + // Call the summarize_context method which uses the summarize_messages function + let (summarized_messages, _) = + self.agent.summarize_context(&self.messages).await?; + + // Update the session messages with the summarized ones + self.messages = summarized_messages; + + // Persist the summarized messages + session::persist_messages( + &self.session_file, + &self.messages, + Some(provider), + ) + .await?; + + output::hide_thinking(); + println!( + "{}", + console::style("Conversation has been summarized.").green() + ); + println!( + "{}", + console::style( + "Key information has been preserved while reducing context length." + ) + .green() + ); + } else { + println!("{}", console::style("Summarization cancelled.").yellow()); + } + continue; } }