Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions crates/goose/src/agents/large_response_handler.rs
Original file line number Diff line number Diff line change
@@ -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::<usize>("GOOSE_MAX_TOOL_RESPONSE_SIZE")
.unwrap_or(DEFAULT_LARGE_TEXT_THRESHOLD)
Comment on lines +9 to +12
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Cache configured response-size limit

Avoid reading GOOSE_MAX_TOOL_RESPONSE_SIZE from Config on every tool result. process_tool_response runs for each tool call, and large_text_threshold() now calls Config::global().get_param(...), which falls through to config-file loading/parsing when the env var is unset. That introduces synchronous filesystem/config-deserialization work on a hot path and can add noticeable latency in tool-heavy sessions compared to the previous constant-time check.

Useful? React with 👍 / 👎.

}

/// Process tool response and handle large text content
pub fn process_tool_response(
response: Result<CallToolResult, ErrorData>,
) -> Result<CallToolResult, ErrorData> {
let threshold = large_text_threshold();
match response {
Ok(mut result) => {
let mut processed_contents = Vec::new();
Expand All @@ -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) => {
Expand Down Expand Up @@ -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]));
Expand Down Expand Up @@ -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]));
Expand Down
4 changes: 4 additions & 0 deletions documentation/docs/guides/environment-variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,7 @@ These variables control how goose handles [tool execution](/docs/guides/goose-pe
| `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**
Expand All @@ -361,6 +362,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
```
Expand Down
Loading