diff --git a/crates/goose/src/agents/large_response_handler.rs b/crates/goose/src/agents/large_response_handler.rs index 2ac5480d41..b3f3e0babc 100644 --- a/crates/goose/src/agents/large_response_handler.rs +++ b/crates/goose/src/agents/large_response_handler.rs @@ -1,14 +1,22 @@ +use crate::config::Config; use chrono::Utc; use rmcp::model::{CallToolResult, Content, ErrorData}; use std::fs::File; use std::io::Write; -const LARGE_TEXT_THRESHOLD: usize = 200_000; +const DEFAULT_LARGE_TEXT_THRESHOLD: usize = 200_000; + +fn large_text_threshold() -> usize { + Config::global() + .get_param::("GOOSE_MAX_TOOL_RESPONSE_SIZE") + .unwrap_or(DEFAULT_LARGE_TEXT_THRESHOLD) +} /// Process tool response and handle large text content pub fn process_tool_response( response: Result, ) -> Result { + let threshold = large_text_threshold(); match response { Ok(mut result) => { let mut processed_contents = Vec::new(); @@ -17,7 +25,7 @@ pub fn process_tool_response( match content.as_text() { Some(text_content) => { // Check if text exceeds threshold - if text_content.text.chars().count() > LARGE_TEXT_THRESHOLD { + if text_content.text.chars().count() > threshold { // Write to temp file match write_large_text_to_file(&text_content.text) { Ok(file_path) => { @@ -107,7 +115,7 @@ mod tests { #[test] fn test_large_text_response_redirected_to_file() { // Create a text larger than the threshold - let large_text = "a".repeat(LARGE_TEXT_THRESHOLD + 1000); + let large_text = "a".repeat(DEFAULT_LARGE_TEXT_THRESHOLD + 1000); let content = Content::text(large_text.clone()); let response = Ok(CallToolResult::success(vec![content])); @@ -166,7 +174,7 @@ mod tests { fn test_mixed_content_handled_correctly() { // Create a response with mixed content types let small_text = Content::text("Small text"); - let large_text = Content::text("a".repeat(LARGE_TEXT_THRESHOLD + 1000)); + let large_text = Content::text("a".repeat(DEFAULT_LARGE_TEXT_THRESHOLD + 1000)); let image = Content::image("image_data".to_string(), "image/jpeg".to_string()); let response = Ok(CallToolResult::success(vec![small_text, large_text, image])); diff --git a/documentation/docs/guides/environment-variables.md b/documentation/docs/guides/environment-variables.md index 2f2108515a..f63c353462 100644 --- a/documentation/docs/guides/environment-variables.md +++ b/documentation/docs/guides/environment-variables.md @@ -364,6 +364,7 @@ These variables control how goose handles [tool execution](/docs/guides/managing | `GOOSE_CLI_TOOL_PARAMS_TRUNCATION_MAX_LENGTH` | Maximum length for tool parameter values before truncation in CLI output (not in debug mode) | Integer | 40 | | `GOOSE_DEBUG` | Enables debug mode to show full tool parameters without truncation. Can also be toggled during a session using the `/r` [slash command](/docs/guides/goose-cli-commands#slash-commands) | "1", "true" (case-insensitive) to enable | false | | `GOOSE_SEARCH_PATHS` | Prepends additional directories to PATH for extension commands | JSON array of paths (for example, `["/usr/local/bin", "~/custom/bin"]`) | System PATH only | +| `GOOSE_MAX_TOOL_RESPONSE_SIZE` | Maximum character count for a single tool response before it is written to a temporary file instead of being included inline in the conversation | Positive integer (e.g., 100000, 200000) | 200000 | | `GOOSE_SHELL` | Overrides the shell used for Developer extension shell commands | Shell executable path or name (for example, `/bin/zsh`, `pwsh`, `C:\cygwin64\bin\bash.exe`) | Unix: `/bin/bash` if present, otherwise `$SHELL`, otherwise `sh`. Windows: `cmd` | **Examples** @@ -379,6 +380,9 @@ export GOOSE_CLI_TOOL_PARAMS_MAX_LENGTH=100 # Show up to 100 characters for too # Add custom tool directories for extensions export GOOSE_SEARCH_PATHS='["/usr/local/bin", "~/custom/tools", "/opt/homebrew/bin"]' +# Lower the tool response size limit for smaller-context models +export GOOSE_MAX_TOOL_RESPONSE_SIZE=100000 + # Use zsh for Developer extension shell commands export GOOSE_SHELL=/bin/zsh ```