Skip to content

Conversation

@roomote
Copy link
Contributor

@roomote roomote bot commented Jul 31, 2025

Fixes #6463

Summary

This PR implements automatic compression of tool results that exceed context window limits to prevent tasks from being unable to continue when tools return large amounts of data.

Changes

  • New compression utility (src/core/tools/compressToolResult.ts):

    • Intelligent truncation using existing truncateOutput function
    • Context-aware compression limits based on model context window size
    • Preserves beginning and end of content for maximum utility
    • Clear compression indicators for the model
  • Integration with tool result processing (src/core/assistant-message/presentAssistantMessage.ts):

    • Automatic compression in pushToolResult function
    • Handles both string and array-based tool results
    • Scales compression limits based on model capabilities
  • Comprehensive test coverage (src/core/tools/__tests__/compressToolResult.spec.ts):

    • Tests for all compression scenarios
    • Validation of compression limits and thresholds
    • Integration testing with existing truncation logic

Technical Details

  • Default limits: 50,000 characters and 1,000 lines for tool results
  • Dynamic scaling: Larger context windows allow larger tool results (up to 2x default)
  • Intelligent truncation: Preserves 20% from beginning and 80% from end of content
  • Clear indicators: Compression notes inform the model about truncation

Testing

  • All new tests pass (19/19)
  • Existing assistant message tests continue to pass (40/40)
  • Linting and type checking successful

Impact

This change ensures that tools returning large results (like search operations) no longer cause tasks to fail due to context window exhaustion, while maintaining the most important parts of the tool output for the model to work with.


Important

Adds tool result compression to prevent context window exhaustion, with dynamic limits and comprehensive testing.

  • New compression utility (compressToolResult.ts):
    • Adds compressToolResult() for compressing tool results exceeding limits.
    • Adds getCompressionLimitsForContextWindow() to determine limits based on context window size.
    • Uses truncateOutput for intelligent truncation.
  • Integration (presentAssistantMessage.ts):
    • Integrates compression in pushToolResult() for string and array tool results.
    • Adjusts compression limits dynamically based on model capabilities.
  • Testing (compressToolResult.spec.ts):
    • Comprehensive tests for compression scenarios and limits.
    • Validates integration with existing truncation logic.

This description was created by Ellipsis for ee6d6db. You can customize this summary. It will automatically update as commits are pushed.

- Add compressToolResult utility with intelligent truncation
- Integrate compression into pushToolResult function
- Scale compression limits based on model context window
- Add comprehensive tests for compression functionality
- Fixes #6463: Tool results that exceed context limits now get compressed
@roomote roomote bot requested review from cte, jr and mrubens as code owners July 31, 2025 02:55
@dosubot dosubot bot added size:L This PR changes 100-499 lines, ignoring generated files. enhancement New feature or request labels Jul 31, 2025
Copy link
Contributor Author

@roomote roomote bot left a comment

Choose a reason for hiding this comment

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

Thank you for implementing tool result compression! This addresses an important issue with context window exhaustion. I've reviewed the changes and found several areas that need attention, particularly around code quality and consistency.

@@ -0,0 +1,114 @@
import { truncateOutput } from "../../integrations/misc/extract-text"
import { DEFAULT_TERMINAL_OUTPUT_CHARACTER_LIMIT } from "@roo-code/types"
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This import is unused and should be removed. The constant isn't referenced anywhere in this file, creating unnecessary coupling to the types package.


if (typeof content === "string") {
cline.userMessageContent.push({ type: "text", text: content || "(tool did not return anything)" })
// Get compression limits based on the model's context window
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This code block (lines 253-256) is duplicated below at lines 269-271. Could we extract this into a helper function to follow DRY principles? Something like getCompressionLimitsForModel would eliminate the duplication.

const compressedLines = compressedResult.split("\n").length

// Add compression info at the beginning to make it clear to the model
const compressionNote = `[Tool result compressed: Original ${originalLength} characters, ${originalLines} lines → Compressed to ${compressedLength} characters, ${compressedLines} lines to prevent context window exhaustion]\n\n`
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The compression note format uses arrow symbol and specific wording that differs from the existing truncateOutput function's format. Should we align these for consistency across the codebase?

} {
// Conservative approach: tool results should not exceed a small percentage of context window
// Assuming roughly 4 characters per token on average
const maxToolResultTokens = Math.floor(contextWindow * 0.1) // 10% of context window
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Missing edge case handling - what happens if contextWindow <= 0 or NaN? This could cause unexpected behavior with Math.floor() and Math.min() operations.

// Conservative approach: tool results should not exceed a small percentage of context window
// Assuming roughly 4 characters per token on average
const maxToolResultTokens = Math.floor(contextWindow * 0.1) // 10% of context window
const characterLimit = Math.min(maxToolResultTokens * 4, DEFAULT_TOOL_RESULT_CHARACTER_LIMIT * 2) // Cap at 2x default
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Consider using named constants for these magic numbers. Something like TOOL_RESULT_CONTEXT_PERCENTAGE = 0.1 and COMPRESSION_CAP_MULTIPLIER = 2 would make the logic clearer.

const characterLimit = Math.min(maxToolResultTokens * 4, DEFAULT_TOOL_RESULT_CHARACTER_LIMIT * 2) // Cap at 2x default

// Line limit scales with character limit
const lineLimit = Math.floor(characterLimit / 50) // Assume ~50 chars per line on average
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The assumption of ~50 characters per line might not hold for all content types. Consider making this configurable or using a more robust calculation based on actual content analysis.

@hannesrudolph hannesrudolph added the Issue/PR - Triage New issue. Needs quick review to confirm validity and assign labels. label Jul 31, 2025
@daniel-lxs daniel-lxs moved this from Triage to PR [Needs Prelim Review] in Roo Code Roadmap Aug 1, 2025
@hannesrudolph hannesrudolph added PR - Needs Preliminary Review and removed Issue/PR - Triage New issue. Needs quick review to confirm validity and assign labels. labels Aug 1, 2025
@daniel-lxs
Copy link
Member

The issue needs better scoping, I'll close this but leave the issue open for discussion on the best solution to this problem

@daniel-lxs daniel-lxs closed this Aug 11, 2025
@github-project-automation github-project-automation bot moved this from New to Done in Roo Code Roadmap Aug 11, 2025
@github-project-automation github-project-automation bot moved this from PR [Needs Prelim Review] to Done in Roo Code Roadmap Aug 11, 2025
@daniel-lxs daniel-lxs deleted the feature/tool-result-compression branch August 11, 2025 15:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request PR - Needs Preliminary Review size:L This PR changes 100-499 lines, ignoring generated files.

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

The task can not continue when a tool call returns too much data

4 participants