diff --git a/crates/goose-cli/src/prompt.rs b/crates/goose-cli/src/prompt.rs index 79d7ae58c..a45933ecc 100644 --- a/crates/goose-cli/src/prompt.rs +++ b/crates/goose-cli/src/prompt.rs @@ -19,6 +19,7 @@ pub trait Prompt { println!("Goose is running! Enter your instructions, or try asking what goose can do."); println!("\n"); } + fn ask_user_for_truncation(&self) -> Result; // Pd8b8 } pub struct Input { @@ -30,10 +31,5 @@ pub enum InputType { AskAgain, // Ask the user for input again. Control flow command. Message, // User sent a message Exit, // User wants to exit the session -} - -pub enum Theme { - Light, - Dark, - Ansi, // Use terminal's ANSI/base16 colors directly. + TruncateFurther, // P3abf } diff --git a/crates/goose/src/agents/extension.rs b/crates/goose/src/agents/extension.rs index db5d5f3bc..4a1c739f2 100644 --- a/crates/goose/src/agents/extension.rs +++ b/crates/goose/src/agents/extension.rs @@ -11,7 +11,7 @@ pub enum ExtensionError { Initialization(ExtensionConfig, ClientError), #[error("Failed a client call to an MCP server: {0}")] Client(#[from] ClientError), - #[error("User Message exceeded context-limit. History could not be truncated to accomodate.")] + #[error("User Message exceeded context-limit. History could not be truncated to accomodate. Please choose to either attempt further truncation or exit.")] ContextLimit, #[error("Transport error: {0}")] Transport(#[from] mcp_client::transport::Error), diff --git a/crates/goose/tests/providers.rs b/crates/goose/tests/providers.rs index 332f3ee76..f7e17ad6d 100644 --- a/crates/goose/tests/providers.rs +++ b/crates/goose/tests/providers.rs @@ -253,11 +253,71 @@ impl ProviderTester { Ok(()) } + async fn test_user_prompt_on_context_length_exceeded(&self) -> Result<()> { // P91ef + // Simulate a scenario where context length is exceeded and user is prompted + let large_message_content = "hello ".repeat(300_000); + + let messages = vec![ + Message::user().with_text("hi there. what is 2 + 2?"), + Message::assistant().with_text("hey! I think it's 4."), + Message::user().with_text(&large_message_content), + Message::assistant().with_text("heyy!!"), + Message::user().with_text("what's the meaning of life?"), + Message::assistant().with_text("the meaning of life is 42"), + Message::user().with_text( + "did I ask you what's 2+2 in this message history? just respond with 'yes' or 'no'", + ), + ]; + + // Test that we get ProviderError::ContextLengthExceeded when the context window is exceeded + let result = self + .provider + .complete("You are a helpful assistant.", &messages, &[]) + .await; + + // Print some debug info + println!("=== {}::user_prompt_on_context_length_exceeded ===", self.name); + dbg!(&result); + println!("==================="); + + // Verify that the user is prompted for further action + assert!( + result.is_err(), + "Expected error when context window is exceeded" + ); + assert!( + matches!(result.unwrap_err(), ProviderError::ContextLengthExceeded(_)), + "Expected error to be ContextLengthExceeded" + ); + + // Simulate user choosing to attempt further truncation + let user_input = Message::user().with_text("Attempt further truncation"); + + let result = self + .provider + .complete("You are a helpful assistant.", &[user_input], &[]) + .await; + + // Print some debug info + println!("=== {}::user_prompt_on_context_length_exceeded_further_truncation ===", self.name); + dbg!(&result); + println!("==================="); + + // Verify that the system continues truncation with a further reduced context limit + assert!( + result.is_ok(), + "Expected success after user chooses to attempt further truncation" + ); + + Ok(()) + } + /// Run all provider tests async fn run_test_suite(&self) -> Result<()> { self.test_basic_response().await?; self.test_tool_usage().await?; self.test_context_length_exceeded_error().await?; + self.test_user_prompt_on_context_length_exceeded().await?; // P91ef Ok(()) } }